从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 $@;
}