正则表达式:排除匹配,没有预见 - 是否可能?

时间:2009-01-21 16:50:19

标签: regex regex-negation

在某些正则表达式中,不支持[负]零宽度断言(前瞻/后瞻)。

这使得排除很难(不可能?)。例如“的每一行都有”foo“,就像这样:

^((?!foo).)*$

可以在不使用外观的情况下实现同样的目标(暂时留出的复杂性和性能问题)?

3 个答案:

答案 0 :(得分:30)

更新:它失败了“在oo之前有两个ff”为@Ciantic pointed out in the comments.


^(f(o[^o]|[^o])|[^f])*$

注意:只是在客户端取消匹配而不是使用上述正则表达式要容易得多。

正则表达式假设每行都以换行符结尾,如果不是,则查看C ++和grep的正则表达式。

Perl,Python,C ++和grep中的示例程序都提供相同的输出。

  • perl

    #!/usr/bin/perl -wn
    print if /^(f(o[^o]|[^o])|[^f])*$/;
    
  • python

    #!/usr/bin/env python
    import fileinput, re, sys
    from itertools import ifilter
    
    re_not_foo = re.compile(r"^(f(o[^o]|[^o])|[^f])*$")
    for line in ifilter(re_not_foo.match, fileinput.input()):
        sys.stdout.write(line)
    
  • C ++

    #include <iostream>
    #include <string>
    #include <boost/regex.hpp>
    
    int main()
    {
      boost::regex re("^(f(o([^o]|$)|([^o]|$))|[^f])*$");
      //NOTE: "|$"s are there due to `getline()` strips newline char
    
      std::string line;
      while (std::getline(std::cin, line)) 
        if (boost::regex_match(line, re))
          std::cout << line << std::endl;
    }
    
  • grep

    $ grep "^\(f\(o\([^o]\|$\)\|\([^o]\|$\)\)\|[^f]\)*$" in.txt
    

示例文件:

foo
'foo'
abdfoode
abdfode
abdfde
abcde
f

fo
foo
fooo
ofooa
ofo
ofoo

输出:

abdfode
abdfde
abcde
f

fo
ofo

答案 1 :(得分:1)

您通常可以查找foo并从客户端代码中反转正则表达式匹配的结果。

举一个简单的例子,假设您要验证字符串是否只包含某些字符。

你可以这样写:

^[A-Za-z0-9.$-]*$

并接受true结果为有效,或者像这样:

[^A-Za-z0-9.$-]

并接受false结果为有效。

当然,这并不总是一个选项:例如,有时您只需将表达式放在配置文件中或将其传递给另一个程序。但值得记住。 您的具体问题,例如,如果您可以使用这样的否定,表达式很多更简单。

答案 2 :(得分:1)

我偶然发现了这个问题,寻找我自己的正则表达式排除解决方案,我试图在我的正则表达式中排除序列。

我对这种情况的初步反应:例如“每条没有”foo“的行”只是在grep中使用-v invert sense of matching选项。

grep -v foo

这将返回文件中与'foo'

不匹配的所有行

这很简单,我有强烈的感觉,我只是误解了你的问题......