От ответа perlfaq6 на Как мне сопоставить регулярное выражение в переменной? :
Нам не нужно жестко кодировать шаблоны в операторе сопоставления (или во всем, что работает с регулярными выражениями). Мы можем поместить шаблон в переменную для дальнейшего использования.
Оператор сопоставления является контекстом с двойными кавычками, поэтому вы можете интерполировать свою переменную, как строку с двойными кавычками. В этом случае вы читаете регулярное выражение как пользовательский ввод и сохраняете его в $ regex. Если у вас есть шаблон в $ regex, вы используете эту переменную в операторе сопоставления.
chomp( my $regex = <STDIN> );
if( $string =~ m/$regex/ ) { ... }
Любые специальные символы регулярного выражения в $ regex все еще являются специальными, и шаблон все еще должен быть действительным, иначе Perl будет жаловаться. Например, в этом шаблоне есть непарные скобки.
my $regex = "Unmatched ( paren";
"Two parens to bind them all" =~ m/$regex/;
Когда Perl компилирует регулярное выражение, он рассматривает скобки как начало совпадения в памяти. Когда он не находит закрывающую скобку, он жалуется:
Unmatched ( in regex; marked by <-- HERE in m/Unmatched ( <-- HERE paren/ at script line 3.
Вы можете обойти это несколькими способами в зависимости от нашей ситуации. Во-первых, если вы не хотите, чтобы какие-либо символы в строке были специальными, вы можете экранировать их с помощью quotemeta, прежде чем использовать строку.
chomp( my $regex = <STDIN> );
$regex = quotemeta( $regex );
if( $string =~ m/$regex/ ) { ... }
Вы также можете сделать это непосредственно в операторе сопоставления, используя последовательности \ Q и \ E. \ Q сообщает Perl, где начинать экранирование специальных символов, а \ E указывает, где остановиться (подробнее см. Perlop).
chomp( my $regex = <STDIN> );
if( $string =~ m/\Q$regex\E/ ) { ... }
В качестве альтернативы, вы можете использовать qr //, оператор кавычек регулярного выражения (подробнее см. Perlop). Он цитирует и, возможно, компилирует шаблон, и вы можете применять к шаблону флаги регулярных выражений.
chomp( my $input = <STDIN> );
my $regex = qr/$input/is;
$string =~ m/$regex/ # same as m/$input/is;
Возможно, вы захотите отследить любые ошибки, обернув вокруг него блок eval.
chomp( my $input = <STDIN> );
eval {
if( $string =~ m/\Q$input\E/ ) { ... }
};
warn $@ if $@;
Или ...
my $regex = eval { qr/$input/is };
if( defined $regex ) {
$string =~ m/$regex/;
}
else {
warn $@;
}