正则表达式和否定整个字符组

时间:2009-06-10 18:04:35

标签: regex

我正在尝试一些我认为应该对我来说相当明显的东西,但事实并非如此。我正在尝试匹配一个不包含特定字符序列的字符串。我已尝试使用[^ab][^(ab)]等匹配不包含'a'或'b'的字符串,或仅包含'a'或仅'b'或'ba'但不匹配'ab'的字符串。我给出的例子不符合'ab'这是真的,但它们也不会单独匹配'a'而我需要它们。有一些简单的方法可以做到吗?

9 个答案:

答案 0 :(得分:311)

使用[^ab]等字符类将匹配不在字符集中的单个字符。 (^是否定的部分)。

要匹配不包含多字符序列ab的字符串,您需要使用否定前瞻:

^(?:(?!ab).)+$


并且正则表达式注释模式中的上述表达是:

(?x)    # enable regex comment mode
^       # match start of line/string
(?:     # begin non-capturing group
  (?!   # begin negative lookahead
    ab  # literal text sequence ab
  )     # end negative lookahead
  .     # any single character
)       # end non-capturing group
+       # repeat previous match one or more times
$       # match end of line/string

答案 1 :(得分:168)

使用否定前瞻:

^(?!.*ab).*$

更新:在下面的评论中,我说这种方法比Peter's answer中给出的方法慢。从那时起我就进行了一些测试,结果发现它确实稍微快一些。然而,偏爱另一种技术的原因不是速度,而是简单性。

另一种技术,将here描述为淬火贪婪令牌,适用于更复杂的问题,例如匹配分隔符文本,其中分隔符由多个字符组成(如HTML,如Luke评论below)。对于问题中描述的问题,这太过分了。

对于任何感兴趣的人,我使用大量的Lorem Ipsum文本进行测试,计算不包含“quo”一词的行数。这些是我使用的正则表达式:

(?m)^(?!.*\bquo\b).+$

(?m)^(?:(?!\bquo\b).)+$

无论是在整个文本中搜索匹配,还是将其分解为行并单独匹配,锚定前瞻一直优于浮动前瞻。

答案 2 :(得分:51)

是的,它被称为负向前瞻。它是这样的 - (?!regex here)。因此abc(?!def)将匹配abc 而不是,然后是def。所以它会匹配abce,abc,abck等。

同样有积极的前瞻 - (?=regex here)。因此abc(?=def)将匹配abc,然后是def。

还有负面和正面的后视 - 分别为(?<!regex here)(?<=regex here)

需要注意的一点是负前瞻是零宽度。也就是说,它不算是占用了任何空间。

所以看起来a(?=b)c可能会匹配“abc”,但事实并非如此。它将匹配'a',然后是'b'的正向前瞻,但它不会向前移动到字符串中。然后它会尝试将'c'与'b'匹配,这将无效。类似地,^a(?=b)b$将匹配'ab'而不是'abb',因为外观是零宽度(在大多数正则表达式实现中)。

有关this

的更多信息

答案 3 :(得分:6)

正如您所描述的那样使用正则表达式是一种简单的方法(据我所知)。如果你想要一个范围,你可以使用[^ a-f]。

答案 4 :(得分:5)

最简单的方法是完全从正则表达式中取消否定:

if (!userName.matches("^([Ss]ys)?admin$")) { ... }

答案 5 :(得分:5)

  

abc(?!def)将匹配abc未遵循   通过def。所以它会匹配abce,abc,   abck,等等,如果我不想要def   也不是xyz会是abc(?!(def)(xyz))   ???

我有同样的问题并找到了解决方案:

abc(?:(?!def))(?:(?!xyz))

这些非计数组由“AND”组合,所以这应该可以解决问题。希望它有所帮助。

答案 6 :(得分:4)

正则表达式[^(ab)]将匹配例如'ab ab ab ab'但不匹配'ab',因为它将匹配字符串'a'或'b'。

你有什么语言/场景?你能从原始集中减去结果,只匹配ab?

如果您正在使用GNU grep,并且正在解析输入,请使用'-v'标志反转您的结果,返回所有不匹配。其他正则表达式工具也具有“返回非匹配”功能。

如果我理解正确,除了那些在任何地方都包含'ab'的项目之外你想要的一切。

答案 7 :(得分:4)

只需在字符串中搜索“ab”,然后否定结果:

!/ab/.test("bamboo"); // true
!/ab/.test("baobab"); // false

看起来更容易,也应该更快。

答案 8 :(得分:3)

在这种情况下,我可能只是完全避免使用正则表达式,并使用类似的内容:

if (StringToTest.IndexOf("ab") < 0)
  //do stuff

这可能也会快得多(快速测试与上面的正则表达式相比,这种方法占据了正则表达式方法的大约25%的时间)。一般来说,如果我知道我正在寻找的确切字符串,我发现正则表达式是过度的。既然你知道你不想要“ab”,那么测试字符串是否包含该字符串是一件简单的事情,而不使用正则表达式。