Метапрограммирование Perl: когда небезопасно использовать quotemeta для значения REPLACEMENT s ///? - PullRequest
3 голосов
/ 12 сентября 2010

Оператор Perl quotemeta обычно работает на стороне ПОИСКА s///, но при генерации кода, который должен быть скомпилирован с eval, как мне защитить ЗАМЕНУдолжен использоваться буквально, но может содержать биты, такие как $1?

С кодом вида

my $replace = quotemeta $literal_replacement;

my $code = eval <<EOCode;
  sub { s/.../$replace/ }
EOCode

когда это приведет к синтаксическим ошибкам или неожиданным результатам?

Ответы [ 3 ]

7 голосов
/ 12 сентября 2010

Насколько я могу судить, perl не выполняет магические действия с $ replace, если вы не добавляете флаг / e на замену.Таким образом, quotemeta всегда изменит ваш результат, так как он содержит множество обратных наклонных черт.

#!/usr/bin/perl

$test="test";

$literal_replacement='Hello $1, or \1';
my $replace = quotemeta $literal_replacement;
$test =~ s/test/$replace/;

print $test,"\n";

возвращает:

Hello\ \$1\,\ or\ \\1

Что, вероятно, не то, что вы хотите:

1 голос
/ 12 сентября 2010

Замена обычно обрабатывается как строка в двойных кавычках, но вы можете изменить это, используя одинарные кавычки в качестве разделителя:

$test =~ s<test>'$replace';
1 голос
/ 12 сентября 2010

Сторона замены - это обычная интерполирующая строка (если только вы не начнете добавлять модификаторы /e, в этом случае она станет столько же строк eval s, сколько существует /e модификаторов.)Perl 5 не волнует, что находится в переменной, которую вы интерполируете в строку.Это так же, как:

my $foo = 5;
my $bar = '$foo';
my $baz = "$foo $bar"; 
print "$baz\n"; #this is 5 $foo not 5 5
...