5

我很难确定在使用 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 输出)。试图逃避其他讨厌的字符也会导致匹配失败。我可以继续尝试不同的组合来逃避什么,但这里有很多变化,希望有人能提供一些见解。

4

3 回答 3

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,可以执行以下操作。您必须转义任何文字空格,您需要以某种方式表示行尾,并且您必须转义文字 # 字符。以前可读的现在是一团糟:

我的 $sc = qr{(>|\s)};
我的 $eol = qr{[\r\n]+};

我的 $re = qr{\# \s+ 使用 \s+ 默认值 \s+ 在 \s+ \.config $eol 中找到 \s+
\* $eol
\* $eol
选项:$eol
$sc \s+ 1\。\s+ opt1 $eol
$sc \s+ 2\。\s+ opt2 $eol
选择\[1-2\?]:\s+
}X;

if ( $output =~ $re ) {
  打印“好的!\n”;
}
别的 {
  打印“哦!\n”;
}
于 2008-11-14T19:56:51.280 回答
7

听起来您真正想要的是Expect,但您最急需寻找的是quotemeta运算符,它将所有对正则表达式具有特殊含义的字符转义。

要直接回答您的问题(但是),除了不带引号的字符(在这种情况下})之外,您至少需要转义,.[$()|*+?{\

于 2008-11-14T20:05:23.573 回答
2

就像布赖恩说的那样,您必须转义分隔符和正则表达式元字符。请注意,在使用qr//x(您是)时,您还必须转义空格字符和#(这是一个注释标记)。您可能实际上并不想在/x这里使用。如果您想安全,您可以转义任何非字母数字字符。

于 2008-11-14T20:08:55.220 回答