似乎JavaScript的RegExp没有找到“最左最长”的匹配

3
我观察到以下结果:
// Test 1:
var re = /a|ab/;
"ab".match(re); // returns ["a"]   <--- Unexpected

// Test 2:
re = /ab|a/;
"ab".match(re); // returns ["ab"]

我希望测试1和2都返回["ab"],这是因为“最左最长”的原则。我不明白为什么正则表达式中2个选项的顺序会改变结果。

2
一个很好的观察,但我看不到问题。 - Chris Hayes
@ChrisHayes,我的假设是“RegExp”应该找到“最左最长”的匹配项。在测试1中,这将是“ab”,比“a”更长。但这并没有发生。 - JoelFan
1
@JoelFan 看起来 JavaScript 没有实现“最左最长匹配”,而是像 Perl 一样采用第一个子表达式匹配。 - Explosion Pills
FYI... Perl 在这方面的表现似乎与 JavaScript 相同。 - JoelFan
2个回答

3
以下是原因:
请注意,备选项从左到右考虑,直到找到匹配项为止。如果左侧备选项匹配,则忽略右侧备选项,即使它可能会产生更好的匹配结果。因此,当模式 /a|ab/ 应用于字符串“ab”时,它只匹配第一个字母。
(来源:Oreilly - Javascript Pocket Reference - 第9章 正则表达式)
谢谢。

哇,我感到非常荣幸能够想到O'Reilly的问题,甚至是逐字逐句地。 - JoelFan

2
这是因为JavaScript没有实现POSIX引擎。
POSIX NFA引擎的工作方式与传统NFA类似,但有一个例外:POSIX引擎总是选择最左边匹配的最长字符串。例如,交替使用cat|category将尽可能匹配完整单词"category",即使第一个备选项("cat")匹配并出现在交替中较早的位置。(参见MRE 153-154)
来源:Oreilly - JavaScript口袋参考书,第4页

尽管@Agustin的回答很有帮助,但我接受了这个答案,因为它回答了“为什么”的问题。 - JoelFan

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