Из ответа perlfaq6 на Как сопоставить регулярное выражение, которое находится в переменной?:
Нам не нужно жестко кодировать шаблоны в операторе match (или во всем, что работает с регулярными выражениями). Мы можем поместить шаблон в переменную для последующего использования.
Оператор match представляет собой контекст с двойными кавычками, поэтому вы можете интерполировать свою переменную так же, как строку с двойными кавычками. В этом случае вы читаете регулярное выражение как пользовательский ввод и сохраняете его в $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.
Вы можете обойти это несколькими способами в зависимости от нашей ситуации. Во-первых, если вы не хотите, чтобы какие-либо символы в строке были специальными, вы можете экранировать их с помощью кавычек перед использованием строки.
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 $@;
Or...
my $regex = eval { qr/$input/is };
if( defined $regex ) {
$string =~ m/$regex/;
}
else {
warn $@;
}
person
brian d foy
schedule
04.01.2010