用于否定组的Perl表达式

时间:2013-08-31 04:02:40

标签: php regex perl preg-match

我有这个日志:

The Foo bar, and Bar foo needs to Foo 
The Bar of Bar foo Bar Foo Foo
Bar bar The Bar of Foo other Foo Bar

我想创建一个perl表达式,只选择不是Foo和Bar的单词。结果日志必须是:

The bar, and foo needs to
The of foo
The of other

我有这个:

^(Foo|Bar)

但它不起作用。

2 个答案:

答案 0 :(得分:3)

如果您尝试从字符串中删除值,则可以使用替换:

my $str = <<EOS;
    The Foo bar, and Bar foo needs to Foo
    The Bar of Bar foo Bar Foo Foo
    Bar bar The Bar of Foo other Foo Bar
EOS
$str =~ s/(?:Foo|Bar) ?//g;
print $str;

>>>The bar, and foo needs to
   The of foo
   bar The of other

请注意,最后一个“小条”(小写)仍在那里;我认为你的帖子里有一个错误。

答案 1 :(得分:3)

如果我理解正确的评论,你想要的是捕获所有不是FooBar的单词,然后可能以某种方式打印它们。这将是做这种事情的一种方式:

/(?<!\S)(?!Foo|Bar)\S+(?!\S)/g

它没有它看起来那么复杂,这里是带注释的版本:

/
    (?<!\S)            # match cannot be preceded by non-whitespace
    (?!Foo|Bar)(\S+)   # capture non-whitespace that is not Foo|Bar
    (?!\S)             # match cannot be followed by non-whitespace
/gx                    # match globally and ignore whitespace in regex

请注意/x就在那里,所以我可以在正则表达式中使用注释和换行符。

这个正则表达式的起点和终点是我们的边界锚点。我们使用这些来确保我们不会得到部分匹配。它们是负面的查找断言,并且替换了稍微简单的\b字边界断言。虽然这里不能使用\b,因为你的字符串中有一个逗号字符。我们使用(?!\S)而不是\s的原因是,虽然它们都匹配空格,但后者与字符串的开头/结尾不匹配。

因为我们已经确定自己无法获得部分匹配,所以我们现在可以在我们的锚点中使用另一个负向前瞻断言的简单替换。即(?!Foo|Bar)。如果不匹配,我们会使用(\S+)捕获字符串。

以下是我为此问题创建的测试用例:

perl -nlwe 'push @a, [/(?<!\S)(?!Foo|Bar)(\S+)(?!\S)/g] }{ print "@$_" for @a'
The Foo bar, and Bar foo needs to Foo
The Bar of Bar foo Bar Foo Foo
Bar bar The Bar of Foo other Foo Bar
^Z
The bar, and foo needs to
The of foo
bar The of other

这使用我们的正则表达式从$_(输入)捕获字符串,并将它们推送到数组引用中的@a数组。输入完成后(在eskimo运算符}{之后),我们打印插值数组引用以添加空格。在这种情况下,"@$_"相当于join " ", @$_