我必须在 Perl 预编译的正则表达式中转义哪些字符?

Posted

技术标签:

【中文标题】我必须在 Perl 预编译的正则表达式中转义哪些字符?【英文标题】:What characters must I escape in a Perl pre-compiled regex? 【发布时间】:2008-11-14 19:50:03 【问题描述】:

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

【问题讨论】:

【参考方案1】:

您必须转义 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 最佳实践 中告诉人们总是将这些选项放在他们的正则表达式中,但您现在明白他为什么错了。你应该只在你想要它们做什么时添加它们,并且你应该只在你知道它们做什么时才添加它们。 :) 如果您想使用 /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”;

【讨论】:

啊!我对“s”和“x”所做的理解与现实相反。因此,$re 中缺少 ''。但是,是的,我在这里也责怪 PbP。 :) 这本书解释了这些选项的作用以及为什么要使用它们……你不能真的为此责怪这本书。 :) 我可以责怪这本书。它说“始终使用 /x 标志”(第 236 页)和“始终使用 /m 标志”(第 237 页)。 “始终”的建议是错误的。 责任完全在于我 :)。快速编辑我的 .perlcriticrc 应该可以解决这个问题。【参考方案2】:

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

要直接回答您的问题(但是),除了不带引号的字符(在本例中为 )之外,您至少需要转义 .[$()|*+?\

【讨论】:

实际上,这是与 Expect 和 Test::More 结合使用的。只是为了示例而缩减代码。【参考方案3】:

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

【讨论】:

以上是关于我必须在 Perl 预编译的正则表达式中转义哪些字符?的主要内容,如果未能解决你的问题,请参考以下文章

在正则表达式中转义特殊字符

perl:如何从预编译版本中获取原始正则表达式?

我应该在 Perl 中转义 shell 参数吗?

如何在 oracle 中转义特殊的正则表达式字符?

需要在正则表达式中转义的所有特殊字符的列表

Java - 在正则表达式中转义元字符 [ 和 ] [重复]