Как я могу создать имя переменной Perl на основе строки?

StackOverflow https://stackoverflow.com/questions/2275463

  •  21-09-2019
  •  | 
  •  

Вопрос

В 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.

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

Это было полезно?

Решение

Если вы пытаетесь очистить старый код, вы можете написать модуль, который экспортирует необходимые переменные.Каждый раз, когда вы чувствуете необходимость вызвать 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";

...тогда ответ будет "Нет". Однако Perl vars 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 отключает эту функцию.

Рафаэль Гарсия-Суарес проявил большую мудрость, когда написал: “Я не знаю, в чем заключается ваша первоначальная проблема, но я предлагаю использовать хэш”.

Смотрите также:

Ответ Синана Юнура действительно лучший.Однако это вызвало мое любопытство, поэтому я немного почитал (perldoc perlmod) и узнал о хеше «package_name::» как о способе доступа к пространству имен пакета.

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

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

print "$main::blah\n";

Это печатает «ссс».

Однако мне пришлось добавить имя пакета в оператор печати, потому что «использовать строгое» все еще не обмануть.Я продолжу поиск — использование vars сейчас не работает.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top