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

kmo*_*511 185 regex

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

Pet*_*ton 325

使用类似的字符类[^ab]将匹配不在字符集内的单个字符.(^作为否定的部分).

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

^(?:(?!ab).)+$
Run Code Online (Sandbox Code Playgroud)


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

(?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
Run Code Online (Sandbox Code Playgroud)

  • 解剖正则表达式对我非常有帮助.谢谢. (19认同)

Ala*_*ore 177

使用否定前瞻:

^(?!.*ab).*$
Run Code Online (Sandbox Code Playgroud)

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

另一种技术,在这里描述为一种驯化的贪婪令牌,适用于更复杂的问题,例如匹配分隔符文本,其中分隔符由多个字符组成(如HTML,如Luke 在下面评论的那样).对于问题中描述的问题,它太过分了.

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

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

(?m)^(?:(?!\bquo\b).)+$
Run Code Online (Sandbox Code Playgroud)

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

  • 如果我认为两种方法之间会有明显的区别,我不会犹豫推荐更快的方法.另一方面,正则表达式是如此不透明(如果不是神秘的),我认为尽可能将知识分解为更小,更易于管理的块是值得的. (28认同)
  • 不要编写针对新手的代码!如果代码难以阅读,请留下评论/文档,以便他们可以学习,而不是使用较少的代码,使他们无知. (26认同)
  • 我相信这更有效:(?:(?!ab).)* (14认同)
  • @Blixit:是的,确实如此.但它也更难阅读,特别是对于正则表达的新手.我发布的那个对于大多数应用程序来说足够高效. (7认同)

Abh*_*pta 56

是的,它被称为负向前瞻.它是这样的 - (?!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',因为外观是零宽度(在大多数正则表达式实现中).

有关页面的更多信息

  • 引用“lookbehind”运算符也很有用,并非所有在线正则表达式解析器/文档都会包含它,即使它有效且有效。 (2认同)

Cop*_*pas 6

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


use*_*268 5

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

if (!userName.matches("^([Ss]ys)?admin$")) { ... }
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用的是文本编辑器,则无法执行此操作. (2认同)

Kra*_*bat 5

abc(?!def)将匹配abc,而不是def.所以它会匹配abce,abc,abck等等.如果我既不想要def也不想xyz它会是abc(?!(def)(xyz))???

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

abc(?:(?!def))(?:(?!xyz))
Run Code Online (Sandbox Code Playgroud)

这些非计数组由"AND"组合,所以这应该可以解决问题.希望能帮助到你.