正则expression式和否定整个字符组

我正在尝试一些我觉得应该相当明显的东西,但事实并非如此。 我想匹配一个不包含特定字符序列的string。 我尝试过使用[^ab][^(ab)]等匹配不包含'a'或'b'的string,或者只匹配'a'或者'b'或者'ba',但不匹配'ab'。 我给出的例子不符合“ab”这是真的,但他们也不会匹配“a”,我需要他们。 有一些简单的方法来做到这一点?

使用负面看法:

 ^(?!.*ab).*$ 

更新:在下面的评论中,我说这个方法比Peter的答案慢。 我从那以后运行了一些testing,发现它实际上稍微快一点。 然而,偏好这种技术的原因不是速度,而是简单。

另一种在这里描述为贪婪的贪婪标记的技术适用于更复杂的问题,比如匹配分隔符由多个字符组成的分隔文本(如Luke 在下面评论的HTML)。 对于问题中描述的问题,这是矫枉过正。

对于任何感兴趣的人,我都会testing一大块Lorem Ipsum文本,计算不包含单词“quo”的行数。 这些是我使用的正则expression式:

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

无论是在全文中search匹配,还是将其分解成单行匹配,锚定的前瞻总是优于浮动的。

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

要匹配一个不包含多字符序列ab的string,您需要使用负向预览:

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

上述expression式在正则expression式注释模式中是:

 (?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 

是的,它被称为消极的前瞻。 它是这样的 – (?!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”匹配,但不会向前移动到string中。 然后它会尝试将'c'和'b'相匹配,这是行不通的。 同样, ^a(?=b)b$将匹配'ab',而不是'abb',因为lookaround是零宽度(在大多数正则expression式实现中)。

更多信息在这个页面上

最简单的方法是将否定从正则expression式中完全拉出来:

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

你所描述的使用正则expression式是简单的方法(据我所知)。 如果你想要一个范围,你可以使用[^ af]。

abc(?!def)将匹配abc,紧接着是def。 所以它会匹配abce,abc,abck等等。如果我不想要def和xyz,它会是abc(?!(def)(xyz))?

我有同样的问题,并find了解决办法:

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

这些不计数的小组由“AND”组合,所以这应该是诀窍。 希望它有帮助。

正则expression式[^(ab)]将匹配例如'ab ab ab ab',但不匹配'ab',因为它将匹配string'a'或'b'。

你有什么语言/场景? 你可以减去原来的结果,只是匹配ab?

如果您使用的是GNU grep,并且正在parsinginput,请使用“-v”标志来反转结果,并返回所有不匹配的结果。 其他的正则expression式工具也有“返回不匹配”的function。

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

在这种情况下,我可能只是简单地避免正则expression式,并采取类似的方式:

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

这可能也会更快(上面的快速testing与正则expression式显示这种方法需要大约25%的正则expression式的时间)。 一般来说,如果我知道确切的string我正在寻找,我发现正则expression式是矫枉过正。 既然你知道你不想要“ab”,那么testing这个string是否包含这个string,而不使用regex是一件简单的事情。

只需在string中search“ab”,然后否定结果:

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

这似乎更容易,也应该更快。