我在Perl中有一个复杂的预编译正则表达式。对于大多数情况下,正则表达式是正确的,并且匹配它应该的一切,不应该没有。除了一点。
基本上我的正则表达式如下:
my $regexp = qr/\b(FOO|BAR|\*)\b/;
不幸的是m/\b\*\b/
与example, *
不匹配。由于误报,只有m/\*/
会执行我无法使用的操作。有没有解决方法?
- 误报为:**
,example*
,exam*ple
正则表达式的用途是什么? - 它应该提取关键字(一个是单个星号),同事已经输入了产品数据。目标是将这些信息从freetext字段转移到原子字段中。
答案 0 :(得分:12)
听起来您希望将*
视为单词字符。
\b
相当于
(?x: (?<!\w)(?=\w) | (?<=\w)(?!\w) )
所以你想要
(?x: (?<![\w*])(?=[\w*]) | (?<=[\w*])(?![\w*]) )
已申请,您将获得以下内容:
qr/
(?: (?<![\w*])(?=[\w*]) | (?<=[\w*])(?![\w*]) )
(FOO|BAR|\*)
(?: (?<![\w*])(?=[\w*]) | (?<=[\w*])(?![\w*]) )
/x
但鉴于我们对中间表达的了解,可以简化为以下内容:
qr/(?<![\w*])(FOO|BAR|\*)(?![\w*])/
答案 1 :(得分:4)
问题是Perl不认为*
是“单词字符”,因此无法识别空格和星号之间的单词边界(而 识别它r
中的*
和foobar*
之间的一个。
解决方案是首先确定你做什么想要考虑“word”和“non-word”字符,然后明确检查。例如,如果您希望您的单词仅包含字母'A'到'Z'(或它们的小写版本)和*
,并且其他所有内容都被视为非单词字符,你可以使用:
/(?<![A-Za-z*])(FOO|BAR|\*)(?![A-Za-z*])/
这将匹配字符串FOO
,BAR
或*
,前提是它们之前或之后没有匹配[A-Za-z*]
的字符。
同样,如果您想要将除空格之外的所有内容都视为非单词字符,则可以使用:
/(?<!\S)(FOO|BAR|\*)(?!\S)/
将匹配FOO
,BAR
或*
,前提是它们之前或后面没有非空格字符。
答案 2 :(得分:2)
怎么样:
my $regexp = qr/(?:\b(FOO|BAR)\b)|(?:^| )\*(?:$| )/;
行动中:
my $re = qr~(?:\b(FOO|BAR)\b)|(?:^| )\*(?:$| )~;
while(<DATA>) {
chomp;
say (/$re/ ? "OK : $_" : "KO : $_");
}
__DATA__
FOO
BAR
*
exam*ple
example*
<强>输出:强>
OK : FOO
OK : BAR
OK : *
KO : exam*ple
KO : example*