我正在尝试实现一个正则表达式,其中包含所有字符串,这些字符串具有任意数量的单词但不能跟随:并忽略匹配(如果有)。我决定使用负面的预测。
/([a-zA-Z]+)(?!:)/gm
string: lame:joker
因为我使用的是字符范围,所以它一次匹配一个字符,只忽略前面的最后一个字符: 在这种情况下,我如何忽略整场比赛?
链接到regex101:https://regex101.com/r/DlEmC9/1
答案 0 :(得分:2)
答案 1 :(得分:2)
该问题与回溯有关:一旦您的 [a-zA-Z]+
变为 :
,引擎会从失败的位置退回,重新检查前瞻匹配并找到当冒号前至少有两个字母时匹配,返回后面没有紧跟 :
的那个。请参阅your regex demo:c
中的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 12
在 12,
中,但不在 12:
中,还有 12c
和 { {1}}12_
matches \d+(?![\d:])
在 12
and 12,
和 12c
中,不在 {{1}仅}。