2017-02-10 22 views
0

Мой код ниже:Видя значение переменной Perl создается во время выполнения

use strict; 

my $store = 'Media Markt'; 
my $sentence = "I visited [store]"; 

# Replace characters "[" and "]" 
$sentence =~ s/\[/\$/g; 
$sentence =~ s/\]//g; 

print $sentence; 

Я вижу следующее на экран:

Я посетил $ магазин

Можно ли увидеть следующий? Я хочу, чтобы увидеть значение $ магазина:

я посетил Media Markt

+1

'My $ store = 'Media Markt'; my $ sentence = "Я посетил $ store"; print $ sentence; ' – AbhiNickz

+0

см. Также: http://stackoverflow.com/q/1091634/632407 – jm666

+1

См. [Что делать, если кто-то отвечает на мой вопрос?] (Http://stackoverflow.com/help/someone -answers) – zdim

ответ

3

Вы, кажется, думаете об использовании строки, 'store' для того, чтобы построить имя переменной, $store. Это доходит до темы symbolic references, и вы отправитесь туда do not want to.

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

use warnings; 
use strict; 

my $store = 'Media Markt'; 
my $time = 'morning'; 

my %repl = (store => $store, time => $time); 

my $sentence = "I visited [store] in the [time]"; 

$sentence =~ s/\[ ([^]]+) \]/$repl{$1}/gex; 

print "$sentence\n"; 

Это выводит строку I visited Media Markt in the morning

Регулярное выражение улавливает что-нибудь между [ ], используя negated character class[^]] (любой символ, кроме ]) , соответствует одному или более раз (+). Затем он заменяет его значением в хеш, используя /e, чтобы оценить заменяемую сторону как выражение. Так как скобки совпадают, они в конечном итоге удаляются. /x позволяет использовать внутренние пространства для чтения.

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

$sentence =~ s{\[ ([^]+) \]}{$repl{$1}//"[$1]"}gex; 

defined-or operator (//) кладет обратно "[$1]" если таковые $repl{$1} возвращается undef (нет ключа $1 в хэш, или он имеет undef значение). Таким образом, строки, не имеющие хеш-пар, не изменяются. Я изменил разделители на s{}{} так, чтобы внутри можно было использовать //.

Это не разрешает вложение (например, [store [name]]), не обрабатывает многострочные строки и имеет другие ограничения. Но он должен работать в разумных случаях.

+0

OP может идти только с массивом объектов. Если она думает о динамически добавленном коде. – Pavel

+0

@paveljurca Я полностью согласен с тем, что есть другие способы преследовать то, что кажется идеей, и что подход OO был бы хорош. – zdim

2

Как я уже говорил вам в группе Perl Programmers Facebook, это очень похоже на один из ответов в FAQ по Perl.

How can I expand variables in text strings?

Если вы можете избежать этого, нет, или если вы можете использовать шаблонную систему, такие как Text :: Template или Template Toolkit, сделать это вместо этого.Вы могли бы даже быть в состоянии получить работу с sprintf или printf:

my $string = sprintf 'Say hello to %s and %s', $foo, $bar; 

Однако для единовременного простого случая, когда я не хочу, чтобы вытащить полную шаблонную систему, я буду использовать строка, в которой есть две скалярные переменные Perl. В этом примере я хочу расширить $ Foo и $ бар до значений их переменных:

my $foo = 'Fred'; 
my $bar = 'Barney'; 
$string = 'Say hello to $foo and $bar'; 

Один из способов я могу сделать, это связан с оператором подстановки и двойной /e флага. Первый /e оценивает $1 на замену и превращает его в $foo. Второй /e начинается с $foo и заменяет его своим значением. $foo, а затем превращается в «Фред», и что, наконец, то, что осталось в строке:

$string =~ s/(\$\w+)/$1/eeg; # 'Say hello to Fred and Barney' 

/e также молча игнорировать нарушение строго, заменяя неопределенные имена переменных с пустой строкой. Поскольку я использую флаг /e (дважды даже!), У меня есть все те же проблемы безопасности, что и у меня с eval в его строковой форме. Если в $foo есть что-то странное, возможно, что-то вроде @{[ system "rm -rf /" ]}, тогда я мог бы попасть в беду.

Чтобы обойти проблему безопасности, я мог бы также вытащить значения из хэша вместо оценки имен переменных. Используя один /e, я могу проверить хеш, чтобы убедиться, что это значение существует, а если нет, я могу заменить отсутствующее значение маркером, в этом случае ??? чтобы сигнализировать, что я что-то пропустил:

my $string = 'This has $foo and $bar'; 
my %Replacements = (
    foo => 'Fred', 
    ); 
# $string =~ s/\$(\w+)/$Replacements{$1}/g; 
$string =~ s/\$(\w+)/ 
      exists $Replacements{$1} ? $Replacements{$1} : '???' 
      /eg; 
print $string; 

и фактической (но действительно не рекомендуется - по причинам, изложенным в вышеприведенном FAQ) ответ на ваш вопрос:

$sentence =~ s/\[(\w+)]/'$' . $1/ee; 

 Смежные вопросы

  • Нет связанных вопросов^_^