C++11正则表达式如何匹配返回所有捕获组?
解决C++11 regex无法获取所有捕获组的问题
嘿,我完全懂你的困扰——你想从FIX格式的字符串里提取所有的键值对,但当前代码只返回了最后一组捕获结果,对吧?这其实是正则引擎处理重复捕获组的典型行为,咱们来一步步搞定它。
为什么你的代码只返回最后一组?
你用的std::regex_match是要求整个字符串完全匹配正则表达式,而你的正则(([0-9]+)=(.*?)\\|)+?里,外层的+?是重复整个捕获组。但C++的std::match_results(也就是cmatch)只会存储每个捕获组最后一次匹配的内容,所以你只能看到最后一个键值对的捕获结果,前面的所有匹配都被覆盖了。
正确的解决方案:用正则迭代器遍历所有匹配
要获取所有的键值对,咱们需要用std::cregex_iterator(针对C风格字符串)或者std::sregex_iterator(针对std::string)来遍历字符串中所有符合正则的子串,每个子串对应一个键值对,然后从每个匹配结果里提取捕获组。
修改后的代码示例
#include <iostream> #include <regex> #include <cstring> int main() { const char* fixMessage = "8=FIXT|9=69|35=5|34=18|49=102|56=asd|115=TESTTESTTEST|52=20170810-15:36:22.500867816|1409=42|"; // 使用原始字符串字面量,避免转义反斜杠,让正则更易读 std::regex e(R"(([0-9]+)=(.*?)\|)"); // 创建迭代器,遍历所有匹配的子串 std::cregex_iterator match_it(fixMessage, fixMessage + std::strlen(fixMessage), e); std::cregex_iterator end_it; // 默认构造的迭代器作为结束标记 int count = 0; for (; match_it != end_it; ++match_it) { const std::cmatch& current_match = *match_it; std::cout << "第" << ++count << "组匹配:\n"; std::cout << " 完整匹配: " << current_match[0] << "\n"; std::cout << " 键(组1): " << current_match[1] << "\n"; std::cout << " 值(组2): " << current_match[2] << "\n\n"; } return 0; }
代码说明
- 调整正则表达式:去掉了外层的
+?,因为我们不需要一次性匹配整个字符串,而是让迭代器逐个找到每个键值对的匹配。 - 使用正则迭代器:
std::cregex_iterator会自动遍历输入字符串中所有符合正则的子串,每次迭代返回的cmatch对象包含当前匹配的所有捕获组。 - 原始字符串字面量:
R"(...)"语法可以避免我们手动转义\,让正则表达式的写法更直观。
额外优化:兼容无结尾|的情况
如果你的FIX消息最后一个键值对可能没有结尾的|,可以把正则调整为:
std::regex e(R"(([0-9]+)=(.*?)(?:\||$))");
这里的(?:\||$)是一个非捕获组,匹配结尾的|或者字符串结束位置,这样就能兼容两种情况了。
内容的提问来源于stack exchange,提问作者Andre
相关产品推荐
相关产品推荐

