You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

代码说明

  1. 调整正则表达式:去掉了外层的+?,因为我们不需要一次性匹配整个字符串,而是让迭代器逐个找到每个键值对的匹配。
  2. 使用正则迭代器:std::cregex_iterator会自动遍历输入字符串中所有符合正则的子串,每次迭代返回的cmatch对象包含当前匹配的所有捕获组。
  3. 原始字符串字面量:R"(...)"语法可以避免我们手动转义\,让正则表达式的写法更直观。

额外优化:兼容无结尾|的情况

如果你的FIX消息最后一个键值对可能没有结尾的|,可以把正则调整为:

std::regex e(R"(([0-9]+)=(.*?)(?:\||$))");

这里的(?:\||$)是一个非捕获组,匹配结尾的|或者字符串结束位置,这样就能兼容两种情况了。

内容的提问来源于stack exchange,提问作者Andre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:53:20