在使用Perl的qr {}构造
时,我很难确定哪些字符必须被转义?我正在尝试为包含大量常规转义字符(#*。>:[])的文本创建多行预编译正则表达式,并且还包含另一个预编译的正则表达式。此外,我需要尽可能严格地进行匹配以进行测试。
my $output = q{# using defaults found in .config
*
*
Options:
1. opt1
> 2. opt2
choice[1-2?]: };
my $sc = qr{(>|\s)}smx;
my $re = qr{# using defaults found in .config
*
*
Options:
$sc 1. opt1
$sc 2. opt2
choice[1-2?]: }mx;
if ( $output =~ $re ) {
print "OK!\n";
}
else {
print "D'oh!\n";
}
错误:
Quantifier follows nothing in regex; marked by <-- HERE in m/# using defaults found in .config
* <-- HERE
*
Options:
(?msx-i:(>|\s)) 1. opt1
(?msx-i:(>|\s)) 2. opt2
choice[1-2?]: / at ./so.pl line 14.
试图逃避星号会导致匹配失败(D'oh输出)。试图逃脱其他讨厌的角色也会导致失败的比赛。我可以继续尝试不同的组合来逃避什么,但这里有很多变化,我希望有人可以提供一些见解。
答案 0 :(得分:14)
您必须转义qr //的分隔符,并且必须转义要用作文字的任何正则表达式元字符。如果你想要那些是文字*,你需要逃避它们,因为*是一个正则表达式量词。
您的问题是您添加的各种正则表达式标志。 / m不执行任何操作,因为您不使用字符串的开头或结尾锚点(^,$)。 / s不执行任何操作,因为您不使用通配符。元字符。 / x使你的正则表达式中的所有空格变得毫无意义,并将#行转换为正则表达式注释。
这就是你想要的,删除正则表达式标志并正确转义:
my $sc = qr{(>|\s)};
my $re = qr{# using defaults found in \.config
\*
\*
Options:
$sc 1\. opt1
$sc 2\. opt2
choice\[1-2\?]: };
虽然Damian Conway告诉人们 Perl Best Practices 总是将这些选项放在他们的正则表达式上,但现在你明白为什么他错了。你应该只在你想要它们的时候添加它们,你应该只在你知道它们做什么时添加它们。 :)如果你想使用/ x,这是你可能会做的。你必须逃避任何文字空格,你需要以某种方式表示行结尾,你必须逃避文字#字符。之前可读的东西现在变得一团糟:
my $sc = qr{(>|\s)}; my $eol = qr{[\r\n]+}; my $re = qr{\# \s+ using \s+ defaults \s+ found \s+ in \s+ \.config $eol \* $eol \* $eol Options: $eol $sc \s+ 1\. \s+ opt1 $eol $sc \s+ 2\. \s+ opt2 $eol choice\[1-2\?]: \s+ }x; if ( $output =~ $re ) { print "OK!\n"; } else { print "D'oh!\n"; }
答案 1 :(得分:7)
听起来你真正想要的是Expect,但你最想要的是quotemeta运算符,它会转义所有对正则表达式有特殊含义的字符。
要直接回答您的问题(但是),除了非引号字符(在这种情况下为}
)之外,您还需要至少逃避.[$()|*+?{\
答案 2 :(得分:2)
就像布莱恩所说,你必须逃脱分隔符和正则表达式元字符。请注意,使用qr//x
(您是)时,您还必须转义空白字符和#(这是注释标记)。你可能实际上并不想在这里使用/x
。如果您想要安全,可以转义任何非字母数字字符。