Как я могу создать имя переменной Perl на основе строки?
Можно ли в Perl создать глобальную переменную на основе строки?
Например, если бы у меня была такая функция:
sub create_glob_var {
my ($glob_var_str) = @_;
# something like this ( but not a hash access).
our ${$glob_var_str};
};
и я назвал это так:
create_glob_var( "bar" );
Как я мог изменить create_glob_var
на самом деле создать глобальную переменную под названием $bar
?
Мой проект использует Perl 5.8.5.
РЕДАКТИРОВАТЬ
Следующее не работает:
use strict;
BEGIN {
sub create_glob_var {
my ($glob_var_str) = @_;
no strict 'refs';
$$glob_var_str = undef; # or whatever you want to set it to
}
create_glob_var("bah");
};
$bah = "blah";
Производит:
Переменная "$bah" не импортируется в /nfs/pdx/home/rbroger1/tmp2.pl строка 12. Глобальный символ "$bah" требует явного имени пакета в строке /nfs/pdx/home/rbroger1/tmp2.pl. Выполнение /nfs/pdx/home/rbroger1/tmp2.pl прервано из-за ошибок компиляции.
ПРИМЕЧАНИЕ. Я понимаю, что использование глобальных переменных вызывает истощение озонового слоя и облысение у мужчин. Я пытаюсь очистить некоторый устаревший код, который уже полностью заражен с использованием глобальных переменных. Один рефактор за раз...
6 ответов
Если вы пытаетесь очистить старый код, вы можете написать модуль, который экспортирует необходимые переменные. Каждый раз, когда вы чувствуете необходимость призвать create_glob_var
вместо этого добавьте переменную в этот пакет и поместите ее в список импорта.
Это поможет вам отслеживать, что происходит и как используются переменные.
package MyVars;
use strict; use warnings;
use Exporter 'import';
our($x, %y, @z);
our @EXPORT_OK = qw( $x %y @z );
Сценарий:
#!/usr/bin/perl
use strict;use warnings;
use MyVars qw( $x %y @z );
$x = 'test';
%y = (a => 1, b => 2);
@z = qw( a b c);
use Data::Dumper;
print Dumper \($x, %y, @z);
Выход:
$ VAR1 = \ 'test'; $ VAR2 = { 'a' => 1, 'b' => 2 }; $ VAR3 = [ "А", "Б", "С" ];
sub create_glob_var {
my ($glob_var_str) = @_;
no strict 'refs';
$$glob_var_str = undef; # or whatever you want to set it to
}
no strict 'refs'
необходимо только если use strict
на самом деле, что это всегда должно быть.
Приложение:
Если вы спрашиваете, есть ли способ написать подпрограмму create_glob_var
такой, что следующий код будет успешным:
use strict;
create_glob_var("bar");
$bar = "whatever";
... тогда ответ "Нет" Тем не менее, Perl's vars
Прагма будет делать то, что вы хотите:
use strict;
use vars qw($bar);
$bar = "whatever";
Но это своего рода старый стиль Perl-кодирования. В настоящее время обычно делают это:
use strict;
our $bar = "blah";
our
Также можно просто объявить глобальные переменные, которые могут быть свободно использованы позже:
our ($foo, @bar, %baz);
# ...
$foo = 5;
@bar = (1, 2, 3);
%baz = (this => 'that');
Вы должны будете использовать eval
но это вообще считается злом. Что-то вроде:
eval("$glob_var_str = \@_;");
РЕДАКТИРОВАТЬ
Только что проверил, что вы можете сделать это только без my
и с no strict refs
,
Попробуйте посмотреть на этот вопрос: есть ли в Perl динамические переменные, подобные PHP?
Короче говоря, похоже, что вы должны быть в состоянии сделать $$glob_var_str = "whatever";
vars
Прагма уже делает тяжелую работу за то, что вы хотите, поэтому положите его на работу:
#! /usr/bin/perl
use warnings;
use strict;
use vars;
BEGIN { vars->import(qw/ $bah /) }
$bah = "blah";
print $bah, "\n";
Если вы предпочитаете записать это create_glob_var
затем используйте
#! /usr/bin/perl
use warnings;
use strict;
use vars;
sub create_glob_var { vars->import("\$$_[0]") }
BEGIN { create_glob_var "bah" }
$bah = "blah";
print $bah, "\n";
В любом случае, выход
вздор
Мне любопытно узнать, почему вы хотите сделать это таким образом, а не объявлять эти переменные с our
, Да, может потребоваться несколько итераций, чтобы поймать их всех, но это все равно краткосрочные исправления, верно?
В общем, вы можете использовать переменную в качестве имени переменной (см. "Символические ссылки" в perlref), но вы действительно, действительно, действительно не хотите этого делать: strict 'refs'
Прагма отключает эту функцию.
Рафаэль Гарсиа-Суарес проявил большую мудрость, когда написал: "Я не знаю, в чем заключается ваша первоначальная проблема, но я предлагаю использовать хэш".
Смотрите также:
Ответ Синан Юнур действительно лучший. Однако это вызвало у меня любопытство, поэтому я немного почитал (perldoc perlmod) и узнал о хеше "package_name::" как способ доступа к пространству имен пакета.
Следующий код добавляет запись в таблицу символов main:: package:
use strict;
my $name = "blah";
my $var = "sss";
$main::{$name} = \$var;
print "$main::blah\n";
Это печатает "sss".
Тем не менее, мне пришлось добавить имя пакета в оператор печати, потому что "использовать строгое" все еще не одурачено. Я буду продолжать искать - использование Vars, кажется, не работает в данный момент.