星号的负面前瞻是如何工作的?

时间:2015-09-18 21:17:46

标签: javascript regex

我试图理解为什么我没有从正则表达式中获得预期的结果。

我已经知道什么是负面预测(显然不是:-))而且星号是重复的零次或多次。

看看这个正则表达式:

a(?![^3])

Regular expression visualization

这将匹配a之后没有non-3的匹配。

所以看看这个测试字符串,粗体部分就是匹配:

  

一个 3333335

好的

另外 - 如果我将正则表达式更改为:

a(?![^3]+)  //notice "+"

Regular expression visualization

它仍将匹配:

  

一个 3333335

这将匹配a,后面没有非3(至少一个)

问题

我的问题在于*

让我们将正则表达式更改为:

a(?![^3]*)

Regular expression visualization

这不符合

  

a3333335

但我的问题是 - 为什么?

根据图纸:

a不应该跟着: 没有 非3

但这是发生的事情:a后面没有任何内容 AND 后面没有非三维

那么为什么它不匹配?

让我的生活变得更加困难:

看看这个正则表达式:

a(?![^3]*7)

这将匹配:

  

一个 3333335

这里发生了什么?

4 个答案:

答案 0 :(得分:6)

问题是星号可以生成空字符串""),你可以说每个字符和下一个字符之间的,都有一个空字符串

鉴于正则表达式:

a(?![^3]*)

并且您使用a33333进行查询,您或多或少地说:如果在a之后有非零或更多次非重复,则拒绝,但是有这样的重复:空字符串,所以甚至没有捕获一个3,它将拒绝。因此匹配如下:

a    (?![^3]*)
"a"     ""   "33333"

(引号标记字符串,此处没有字符)

你可以这么说,负面前瞻,正常表达式上的 Kleene明星总会拒绝(必须小心,在句子中我的意思是Kleene明星统一了"整个"正则表达式,这 not 意味着包含Kleene星的负向前瞻总是拒绝。

您的图片也显示了这一点:

enter image description here

它说如果没有跟着,就意味着它与盒子里面的内容不匹配。问题是,它不需要单个字符到达框的末尾。

这不适用于a(?![^3]*7):在这里你说" *如果您遇到零或更多非3 ,然后是七,则拒绝。由于正则表达式[^3]*73333335不匹配,因此前瞻不会拒绝匹配。

答案 1 :(得分:5)

问题是*会重复 或更多次。包含非3s(也称为空字符串)。没有什么不代表字符串的结尾,它意味着字面意思 nothing (空字符串)。

7的示例有效的原因是因为前瞻会尝试匹配尽可能多的非3。在a之后的位置,即非3s。之后,它将尝试完全匹配一个7 。但是下一个字符 3 ,因此前瞻不会使a的匹配失败。

答案 2 :(得分:3)

理解原因:

a(?![^3]*)

无法匹配您可以将前瞻更改为:

a(?!.*)

也会失败并且理由与你的前瞻断言相同,a后面跟包含空字符串的任何内容都不会返回false,因此你的正则表达式总会失败。< / p>

第二个正则表达式是这样的:

a(?![^3]*7)

成功,因为输入中确实没有non-3的0个或更多,后跟7

如果您将输入更改为例如a7然后它将失败。

答案 3 :(得分:0)

问题在于*的行为与其他任何地方的行为方式相同。

[^ 3] * 会匹配每个字符串,因为它匹配“尽可能多的不包含3个字符串”。

a(?![^ 3] * 7)应匹配“任何'a'后面没有尽可能多的'3',包括无和'7'。”这相当于“任何'a'没有后跟7,除非他们被'3'分开。”