为什么可选的0宽捕获组中的预测会阻止该组匹配?

时间:2018-04-28 07:25:27

标签: javascript regex

考虑以下正则表达式:

(^.)?

如果可能,这匹配字符串开头的单个字符:

>> 'ab'.match(/(^.)?/)
Array [ "a", "a" ]

但是,将.包裹在预测中会导致它停止工作:

>> 'ab'.match(/(^(?=.))?/)
Array [ "", undefined ]

undefined的值表示该组不匹配,而不是匹配空字符串。但我不明白前瞻如何阻止群体匹配。我希望在这里获得["", ""]的结果。

更奇怪的是,只有当周围的捕获组的宽度为0时才会出现这种情况。如果我们将^锚更改为更长的时间,它会再次正常工作:

>> 'ab'.match(/(a(?=.))?/)
Array [ "a", "a" ]

删除使组成为可选的?也会修复输出:

>> 'ab'.match(/(^(?=.))/)
Array [ "", "" ]

有人可以解释为什么会这样吗?这对我没有任何意义。

1 个答案:

答案 0 :(得分:2)

这不需要涉及前瞻。任何以空匹配结束并且本身是可选的组都不匹配。

> /()/.exec('foo')
['', '']

> /()?/.exec('foo')
['', undefined]

这很奇怪,是的。

> /(.*?)/.exec('foo')
['', '']

> /(.*?)?/.exec('foo')
['f', 'f']

a V8 test case表明行为是预期的。 This part of the spec

  

如果min为零且y的endIndex等于x的endIndex,则返回失败。

似乎相关但很难理解。如果它实际上导致了这里的行为(同时试图避免组匹配连续的空字符串?),我认为这是一个规范错误。其他语言的行为不一样。 (并非他们必须,但这是另一次罢工。)

实际上,the behaviour has been described before有关于在规范中解释的评论,但它实际上并非解释。 (有一个(a*)*音符没有相应的输出,加上前面提到的步骤,没有任何理由提供,除了关于重复空匹配问题的其他一些说明,其他人似乎已经以更直观的方式解决了。)

的Python

>>> re.match(r'(.*?)?', 'foo').group(0, 1)
('', '')

.NET

> Dim m = Regex.Match("foo", "(.*?)?")
> m.Success
True
> m.Length
0

红宝石

> 'foo' =~ /(.*?)?/
0
> $1
""

的Perl

> 'foo' =~ /(.*?)?/
('')