在libc++上,为什么regex_match("tournament",regex("tour|to|tournament"))失败?

On libc++, why does regex_match("tournament", regex("tour|to|tournament")) fail?

本文关键字:tournament regex to libc++ 失败 tour match 为什么      更新时间:2023-10-16

Inhttp://llvm.org/svn/llvm-project/libcxx/trunk/test/re/re.alg/re.alg.match/ecma.pass.cpp,存在以下测试:

    std::cmatch m;
    const char s[] = "tournament";
    assert(!std::regex_match(s, m, std::regex("tour|to|tournament")));
    assert(m.size() == 0);

为什么这场比赛要失败?

在VC++2012和boost上,匹配成功
在Chrome和Firefox的Javascript上,"tournament".match(/^(?:tour|to|tournament)$/)成功了。

只有在libc++上,匹配才会失败。

我相信测试是正确的。在re.alg下的所有libc++测试中搜索"锦标赛",并比较不同的引擎如何处理regex("tour|to|tournament"),以及regex_searchregex_match的不同,这很有指导意义。

让我们从regex_search:开始

awk,egrp,扩展:

regex_search("tournament", m, regex("tour|to|tournament"))

匹配整个输入字符串:"锦标赛"。

ECMAScript:

regex_search("tournament", m, regex("tour|to|tournament"))

只匹配输入字符串的一部分:"tour"。

grep,基本:

regex_search("tournament", m, regex("tour|to|tournament"))

根本不匹配。"|"字符并不特殊。

awk、egrp和extended将通过交替尽可能多地匹配。但是ECMAScript的替换是"有序的"。这在ECMA-262中有规定。一旦ECMAScript匹配了替换中的一个分支,它就会退出搜索。该标准包括以下示例:

/a|ab/.exec("abc")

返回结果"a"而不是"ab"。

<plug>

Jeffrey E.F.Friedl在《掌握正则表达式》一书中也对此进行了深入讨论。如果没有这本书,我不可能实现<regex>。我会坦率地承认,关于正则表达式,我所不知道的还有很多,而不是我所知道的。

在关于交替的章节末尾,作者指出:

如果你第一次阅读时就理解了这一章的所有内容你可能一开始就没读过。

相信它!

</plug>

无论如何,ECMAScript只匹配"tour"。只有整个输入字符串匹配时,regex_match算法才会返回成功。由于只有输入字符串的前4个字符匹配,因此与awk、egrp和extended不同,ECMAScript返回false,cmatch大小为零。