否定前瞻不适用于角色范围

时间:2017-09-27 22:54:14

标签: python regex regex-lookarounds negative-lookahead

我正在尝试实现一个正则表达式,其中包含所有字符串,这些字符串具有任意数量的单词但不能跟随:并忽略匹配(如果有)。我决定使用负面的预测。

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

因为我使用的是字符范围,所以它一次匹配一个字符,只忽略前面的最后一个字符: 在这种情况下,我如何忽略整场比赛?

链接到regex101:https://regex101.com/r/DlEmC9/1

2 个答案:

答案 0 :(得分:2)

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

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

Here's an example run

答案 1 :(得分:2)

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

向负前瞻添加隐式要求

因为您只需要匹配后面没有冒号的字母序列,所以您可以明确添加一个隐含的条件:并且后面没有另一个字母

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

参见regex demo。由于 [A-Za-z]: 都匹配单个字符,因此将它们放在单个字符类中是有意义的,因此 [A-Za-z]+(?![A-Za-z:]) 更好。

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

作为 @scnerd suggests,词边界在这些情况下也有帮助,但总有一个问题:词边界的含义取决于上下文(请参阅 {{3} 中的许多ifs }}).

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

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

词边界何时失效?

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

  • \d+\b(?!:) regex demo 1212, 中,但不在 12: 中,还有 12c 和 { {1}}
  • 12_ matches \d+(?![\d:])12 and 12,12c 中,不在 {{1}仅}。