Как я уже говорил вам в группе Perl Programmers в Facebook, это очень похоже на один из ответов в Perl FAQ.
Как я могу раскрыть переменные в текстовые строки?
Если вы можете этого избежать, не делайте этого или если вы можете использовать систему шаблонов, такую как Text :: Template или Template Toolkit, сделайте это вместо этого. Возможно, вы даже сможете выполнить эту работу с помощью sprintf
или printf
:
my $string = sprintf 'Say hello to %s and %s', $foo, $bar;
Однако для одноразового простого случая, когда я не хочу извлекать полную систему шаблонов, я буду использовать строку, в которой есть две скалярные переменные Perl. В этом примере я хочу расширить $ foo и $ bar до значений их переменных:
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;