如何在Perl中使用正则表达式中的分词,星号,分词?

时间:2014-02-04 15:28:55

标签: regex perl

我在Perl中有一个复杂的预编译正则表达式。对于大多数情况下,正则表达式是正确的,并且匹配它应该的一切,不应该没有。除了一点。

基本上我的正则表达式如下:

my $regexp = qr/\b(FOO|BAR|\*)\b/;

不幸的是m/\b\*\b/example, *不匹配。由于误报,只有m/\*/会执行我无法使用的操作。有没有解决方法?

来自评论的

- 误报为:**example*exam*ple

正则表达式的用途是什么? - 它应该提取关键字(一个是单个星号),同事已经输入了产品数据。目标是将这些信息从freetext字段转移到原子字段中。

3 个答案:

答案 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*])/

这将匹配字符串FOOBAR*,前提是它们之前或之后没有匹配[A-Za-z*]的字符。

同样,如果您想要将除空格之外的所有内容都视为非单词字符,则可以使用:

/(?<!\S)(FOO|BAR|\*)(?!\S)/

将匹配FOOBAR*,前提是它们之前或后面没有非空格字符。

答案 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*