JavaScript和PHP中前瞻断言的懒惰程度差异

3
“我对JavaScript和PHP处理以下正则表达式的方式之间的差异感到困惑。

在JavaScript中,”

'foobar'.replace(/(?=(bar))/     , '$1');
'foobar'.replace(/(?=(bar))?/    , '$1');
'foobar'.replace(/(?:(?=(bar)))?/, '$1');

分别导致
foobarbar
foobar
foobar

如下所示:

如此显示在jsFiddle上。

然而,在PHP中,

echo preg_replace('/(?=(bar))/', '$1', "foobar<br/>");
echo preg_replace('/(?=(bar))?/', '$1', "foobar<br/>");
echo preg_replace('/(?:(?=(bar)))?/', '$1', "foobar<br/>");

结果是,
foobarbar

Warning: preg_replace() [function.preg-replace]: Compilation failed: nothing to repeat at offset 9 in /homepages/26/d94605010/htdocs/lz/writecodeonline.com/php/index.php(201) : eval()'d code on line 2
foobarbar

我不太担心警告。但似乎在JavaScript中,前瞻断言比在PHP中更“懒惰”。为什么会有差异?这是引擎中的一个漏洞吗?哪个理论上更“正确”?
1个回答

2
真正的区别其实很简单:
在 JavaScript 中,除非使用 /g 标志(全局),否则 replace 只会替换第一个匹配项。而在 PHP 中,preg_replace 会替换所有匹配项。
第三个模式 (?:(?=(bar)))? 可以在任何位置匹配空字符串,并在某些位置捕获 "bar"。如果没有 /g 标志,则它只会在字符串开头匹配一次。
如果你使用了更明显的替换字符串,比如 [$1],那么你很容易看出区别。
PHP示例:http://ideone.com/8Mjg6
JavaScript示例,没有/ghttp://jsfiddle.net/qKb4b/3/
JavaScript示例,有/ghttp://jsfiddle.net/qKb4b/2/

我还要指出,"懒惰"是正则表达式中的另一个概念,与这个问题无关。


我猜我的研究完全是错的。感谢指出。 - dan-lee
谢谢Kobi,很抱歉晚才接受。我还没有机会回去进一步学习它。我最终会回来报告的。 - Andrew Cheong

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