c++ std::regex, smatch在模式字符串中只保留一次子表达式

c++ std::regex, smatch retains subexpressions only once for their apperance in a pattern string

本文关键字:保留 一次 表达式 regex std smatch 字符串 模式 c++      更新时间:2023-10-16

我有以下代码:

    int main()
    {
        regex reg_expr("(\([A-Z],[A-Z]\))(?:\s(\([A-Z],[A-Z]\)))*");
        //regex reg_expr("(\([A-Z],[A-Z]\))(?:\s(\([A-Z],[A-Z]\)))*\s(\([A-Z],[A-Z]\))");
        smatch sm;
        string input("(A,B) (C,D) (F,W) (G,K) (R,M)");
        //string input("(A,B) (C,D) (F,W)");
        if (regex_match(input, sm, reg_expr)) {
            cout << "truen";
            cout << sm.size() << "n";
            for (int i = 0; i < sm.size(); i++) {
                //if (sm[i].length())
                    cout << "submatch number " << i << ": " << sm[i].str() << 'n';
            }
        } else
            cout << "false";
    return 0;
    }

一切正常,除了"smatch sm"对于正则表达式字符串中指定的每个子表达式只有一个子字符串。例如,对于下面的测试字符串:

 (A,B) (C,D) (F,W) (G,K) (R,M)

正确匹配
 (([A-Z],[A-Z]))(?:s(([A-Z],[A-Z])))*

正则表达式,"sm"只有三个子字符串:一个是整个字符串,另外两个是"(A,B)"answers"(R,M)","(C,D)","(F,W)","(G,K)"缺失,但它们是匹配的。

看起来(?:s(([A-Z],[A-Z])))*被正则表达式正确地理解为0个或更多的子表达式应该匹配,但是似乎有一个错误,只有一个子表达式存储在std::smatch sm中。
这是一个库错误(这是不太可能的)还是我做错了什么?欢迎您的帮助和建议!

这不是一个bug,但几乎是一个普遍的行为(除了PyPi Python regex模块,. net和(如果用适当的选项编译)Boost),当重复捕获只将最后匹配的项存储在其缓冲区中。

有关详细信息,请参阅重复捕获组与捕获重复组文章。

在您的情况下,您可以使用常规的 std::sregex_iterator :
int main() {
    std::regex reg_expr(R"(([A-Z],[A-Z]))");
    string input("(A,B) (C,D) (F,W) (G,K) (R,M)");
    for(std::sregex_iterator i = std::sregex_iterator(input.begin(), input.end(), reg_expr);
        i != std::sregex_iterator();
        ++i)
    {
        std::cout << (*i).str() << std::endl;
    }
    return 0;
}

参见c++演示

注意我使用的是原始字符串文字R"(...)",其中只需要1个反斜杠来转义regex元字符。

相关文章: