c ++ std :: regex,smatch只保留一次子表达式,因为它们在模式字符串中的外观

时间:2016-11-02 21:57:54

标签: c++ regex

我有以下代码:

    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 << "true\n";
            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)”和“(R,M)”,“(C,D) “,”(F,W)“,”(G,K)“缺失,但它们匹配。

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

1 个答案:

答案 0 :(得分:2)

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

有关详情,请参阅Repeating a Capturing Group vs. Capturing a Repeated Group文章。

在您的情况下,您可以使用常规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++ demo

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