为什么懒惰量词后面跟着一个问号会变得贪婪?

5
为什么"hello".match(/^(.*?)?/)[0] 的值是"h"而不是""
换句话说,为什么在使用懒惰模式表达式(.*?)之后再加上一个零或一次量词?会使它有点贪心呢?

有趣的观察。但我不确定答案会很令人兴奋。我猜测一个?量词将产生许多零长度的匹配,这是相当无用的 - 即使/^.?/只匹配“h”,我也不确定是否有匹配""的价值,即使它是有效结果。 - VLAZ
3
进一步混淆 - "hello".match(/^(.*?){0,2}/)[0] # => "he" - ndnenkov
1
@VLAZ:为什么要跳过它?去掉第二个?已经导致匹配长度为零。重新加上?根本不需要跳过该匹配项。我完全期望它能匹配成功。 - user541686
确实很奇怪,会在不同的正则表达式引擎中产生不同的匹配结果。另一方面,当进行奇怪的操作时,其他奇怪的事情也许就会发生 :) - bobble bubble
2
regex101显示这只在JavaScript中是这种情况:https://regex101.com/r/3oYGgl/1。其它的语言版本会返回零长度匹配。 - Mark Whitaker
显示剩余6条评论
1个回答

3
内部量词并非变得“贪婪”,而是试图避免匹配完全为空的部分。这就是为什么“.*”仍然只匹配第一个字符,而不是整个单词的原因。
这是JavaScript正则表达式的一种奇怪情况。带有贪婪量词的空匹配部分与其他常见的正则表达式引擎处理方式略有不同。真正的原因相当复杂。详见:在JavaScript中行为不同的贪婪性? 解决方法是将外部量词也设为lazy,加上一个问号:
"hello".match(/^(.*?)??/)[0] // output: ""

哇,我明白了,谢谢! - user541686

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接