我在尝试一些我觉得对我来说应该相当明显的事情,但事实并非如此。我试图匹配一个不包含特定字符序列的字符串。我尝试使用[^ab], [^(ab)]等来匹配不包含'a'或'b'的字符串,或只包含'a'或'b'或'ba',但不匹配'ab'。我给出的例子不能匹配ab,这是真的,但它们也不能单独匹配a,我需要它们。有什么简单的方法吗?


当前回答

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

其他回答

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

要匹配不包含多字符序列ab的字符串,你需要使用负前向:

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

上面的表达式在regex注释模式下解析为:

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

只需在字符串中搜索“ab”,然后对结果求反:

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

它看起来更简单,也应该更快。

最简单的方法是将否定完全从正则表达式中移除:

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

使用消极前视:

^(?!.*ab).*$

更新:在下面的评论中,我说过这种方法比彼得的回答中给出的要慢。从那以后,我进行了一些测试,发现它确实快了一些。然而,与其他技术相比,更喜欢这种技术的原因不是速度,而是简单。

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

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

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

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

无论我是在整个文本中搜索匹配,还是将其分解成行并单独匹配它们,锚定的前向始终优于浮动的前向。

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