Как сохранить подменю regex (search/replace) в переменной, аналогичной qr//

Я пытаюсь сохранить регулярное выражение s/ / /g как переменную (без большой удачи).

Вот пример, который использует обычное совпадение, чтобы показать, что я намерен делать.

my %file_structure = (
    header => qr/just another/,
    table  => qr/perl beginner/,
)

Теперь я могу вызвать это с помощью $line =~ $file_structure{'header'}, и он вернет undef или true, если шаблон совпадает.

Однако я хотел бы сказать $line =~ $file_structure{'foo'}, где $file_structure{'foo'} содержит что-то вроде s/beginner/hacker/g.

Ответ 1

Вы должны хранить 2 части отдельно:

my %file_structure = (
    foo => {pat => qr/beginner/, repl => 'hacker'},
);

my $line = 'just another perl beginner';
$line =~ s/$file_structure{foo}{pat}/$file_structure{foo}{repl}/;
print "$line\n";

Что было бы гораздо безопаснее, чем прибегать к злой "eval EXPR":

my %file_structure = (
    foo => 's/beginner/hacker/',
);

my $line = 'just another perl beginner';
eval "\$line =~ $file_structure{foo}";
print "$line\n";

Ответ 2

Как вы уже выяснили, нет способа прямого хранения регулярного выражения подстановки, например, регулярное выражение соответствия (с qr//). Вы можете разбить детали и перекомпоновать их как шоу tadmc. Другой способ сделать это - сохранить подстановку в подпрограмме:

my %file_structure = (
   foo_uses_default => sub {s/foo/bar/},
   foo_takes_arg    => sub {$_[0] =~ s/foo/bar/},
   foo_does_either  => sub {(@_ ? $_[0] : $_) =~ s/foo/bar/},
);

$file_structure{foo_uses_default}() for ...;
$file_structure{foo_uses_arg}($_)   for ...;