在带有加号量词的字符范围后负先行不起作用

Negative lookahead not working after character range with plus quantifier

我正在尝试实现一个正则表达式,其中包括所有具有任意数量的单词但不能后跟 : 的字符串,如果匹配则忽略。我决定用消极的眼光看待它。

/([a-zA-Z]+)(?!:)/gm
string: lame:joker

因为我使用的是一个字符范围,它一次匹配一个字符并且只忽略 : 之前的最后一个字符。 在这种情况下如何忽略整个匹配?

Link 到 regex101:https://regex101.com/r/DlEmC9/1

+ 之后进行单词边界检查 \b 以要求它到达单词的末尾。

([a-zA-Z]+\b)(?!:)

Here's an example run.

此问题与 回溯 相关:一旦您的 [a-zA-Z]+ 到达 :,引擎就会从失败的位置后退,重新检查前瞻匹配并在冒号前至少有两个字母时找到一个匹配项,返回没有紧跟 : 的那个。参见your regex democ:real中的c没有匹配到,因为没有回溯到的位置,real:c中的rea匹配到,因为a没有紧跟 :.

向否定先行添加隐式要求

由于您只需要匹配不带冒号的字母序列,您可以显式添加一个隐含的条件:且不带另一个字母[=7​​3=]:

[A-Za-z]+(?![A-Za-z]|:)
[A-Za-z]+(?![A-Za-z:])

regex demo。由于[A-Za-z]:都匹配一个字符,所以将它们放在一个字符class中是有意义的,所以,[A-Za-z]+(?![A-Za-z:])更好。

使用单词边界防止回溯到类似单词的模式

, word boundaries can also help in these situations, but there is always a catch: word boundary meaning is context dependent (see a number of ifs in the word boundary explanation).

[A-Za-z]+\b(?!:)

在这里是一个有效的解决方案,因为输入意味着单词以非单词字符结尾(即字符串结尾,或字母、数字和下划线以外的字符)。见 regex demo.

什么时候单词边界失效?

\b 当主要消费模式应该匹配时,即使粘附到其他单词字符,也不会是正确的选择。最常见的例子是匹配数字:

  • \d+\b(?!:) matches 1212, 中,但不在 12: 12c12_
  • \d+(?![\d:])matches1212,12c12_,不是仅限 12: