Как создать имя переменной 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";

выдает:

Variable "$bah" is not imported at /nfs/pdx/home/rbroger1/tmp2.pl line 12.
Global symbol "$bah" requires explicit package name at /nfs/pdx/home/rbroger1/tmp2.pl line 12.
Execution of /nfs/pdx/home/rbroger1/tmp2.pl aborted due to compilation errors.

Примечание я понимаю, что использование глобальных переменных причин истощение озона и мужская плешивость. Я пытаюсь очистить некоторый устаревший код, который уже полностью заражен использованием глобальных переменных. Один рефакторинг одновременно...

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 = [
          'a',
          'b',
          'c'
        ];

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";

...тогда ответ "Нет.- Однако Перл! .. --8--> pragma сделает то, что вы хотите:

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');

попробуйте посмотреть на этот вопрос: имеет ли Perl динамические переменные, подобные PHP?

короче, похоже, вы должны быть в состоянии сделать $$glob_var_str = "whatever";


вам придется использовать eval, но это обычно считается злом. Что-то вроде:

eval("$glob_var_str = \@_;");

редактировать

только что проверено, что вы можете сделать это только без my и no strict refs.


на vars pragma уже делает тяжелый подъем для того, что вы хотите, поэтому положите его на работу:

#! /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";

в любом случае, выход

blah

мне любопытно узнать, почему вы хотите сделать это таким образом, а не объявлять эти переменные с our. Да, может потребоваться несколько итераций, чтобы поймать их все, но это краткосрочные исправления в любом случае, правильно?

в общем, вы можете использовать переменную в качестве имени переменной (см. "символические ссылки" в perlref), но ты действительно, действительно,действительно не хочу этого делать: включение strict 'refs' pragma отключает эту функцию.

Читайте также:


ответ Sinan Ünür действительно лучший. Однако это вызвало мое любопытство, поэтому я немного почитал (perldoc perlmod)и узнал о хэше "package_name::" как способ доступа к пространству имен пакета.

следующий код добавляет запись в таблицу символов main:: package:

use strict;
my $name = "blah";
my $var = "sss";
$main::{$name} = $var;

print "$main::blah\n";

это печатает "sss".

однако мне пришлось добавить имя пакета в оператор печати, потому что "use strict" все еще не обманут. Я буду продолжать искать-использовать vars не кажется, работает в данный момент.