位置:首页 > C++ > c++11 正则表达式 std::regex写法与异常处理

c++11 正则表达式 std::regex写法与异常处理

时间:2026-08-10  |  作者:冻月看渠  |  阅读:0

C++11正则表达式是标准库提供的文本匹配能力,核心类型是std::regex,常配合std::regex_match、std::regex_search、std::sregex_iterator和std::regex_replace使用。它适合处理格式校验、字段提取、批量替换等常见任务;只要把匹配、分组、转义和异常处理几部分理顺,就能较稳定地落地到实际代码中。

基本类型与语法

使用C++11正则表达式需要包含regex头文件,编译时至少启用C++11标准,例如g++ -std=c++11 main.cpp。std::regex负责保存编译后的表达式,std::smatch用于接收针对std::string的匹配结果,std::cmatch则适用于字符数组。默认语法是std::regex_constants::ECMAScript;如果需要,还可以在构造时传入std::regex_constants::basic、extended等语法模式,或叠加std::regex_constants::icase实现大小写不敏感匹配。例如std::regex re("hello", std::regex_constants::icase);可以同时匹配Hello、HELLO和hello。转义时要区分C++字符串和正则语法两层含义:普通字符串里的d+表示把d+交给正则引擎,而原始字符串R"(d+)"会保留反斜杠本意,更适合书写复杂表达式。若要匹配文本中的单个反斜杠,普通字符串常写成\,原始字符串可写成R"()",可读性差异会非常明显。

  • std::regex:创建和保存正则表达式
  • std::smatch:保存std::string的匹配结果
  • std::regex_error:表示表达式编译或执行错误
  • 默认语法为ECMAScript,可在构造时切换basic、extended等模式
  • 可通过std::regex_constants::icase设置大小写不敏感匹配

完整匹配与局部查找

std::regex_match要求整个目标字符串都符合表达式,适合校验邮箱、日期或编号等完整格式;std::regex_search只需在字符串中找到一个符合条件的片段,更适合日志检索和字段提取。下面是一个可直接编译的最小示例,分别演示完整匹配、局部查找和捕获分组读取:

#include 
#include 
#include 

int main() {
    std::string code = "AB-1024";
    std::regex full_re(R"([A-Z]{2}-d{4})");
    if (std::regex_match(code, full_re)) {
        std::cout << "match whole string" << std::endl;
    }

    std::string text = "订单号: AB-1024, 状态: done";
    std::smatch match;
    std::regex search_re(R"(([A-Z]{2})-(d{4}))");
    if (std::regex_search(text, match, search_re)) {
        std::cout << match.str(0) << std::endl; // AB-1024
        std::cout << match.str(1) << std::endl; // AB-1024
        std::cout << match.str(2) << std::endl; // AB
        std::cout << match.str(3) << std::endl; // 1024
    }
}

运行后可看到regex_match用于整串校验,regex_search用于提取首个命中片段。match.str(0)表示完整命中内容,match.str(1)、match.str(2)等依次对应各捕获组;如果使用match[0]、match[1]也能读取相同结果。

  • std::regex_match用于验证整个字符串
  • std::regex_search用于查找第一个匹配片段
  • match.str(0)读取完整结果,match.str(1)起读取各捕获分组
  • match[0]、match[1]与match.str(0)、match.str(1)是常见等价写法

遍历与替换

需要查找全部匹配项时,可以使用std::sregex_iterator遍历目标字符串,每次取得一个匹配结果。需要修改文本时,可调用std::regex_replace,将所有符合表达式的内容替换为指定字符串。下面的示例同时演示全部遍历、分组读取和在替换模板中使用$1、$2重排内容:

#include 
#include 
#include 

int main() {
    std::string text = "2026-08-05 2026-09-01";
    std::regex date_re(R"((d{4})-(d{2})-(d{2}))");

    for (std::sregex_iterator it(text.begin(), text.end(), date_re), end; it != end; ++it) {
        const std::smatch& m = *it;
        std::cout << m.str(0) << " -> year=" << m.str(1)
                  << ", month=" << m.str(2)
                  << ", day=" << m.str(3) << std::endl;
    }

    std::string replaced = std::regex_replace(text, date_re, "$3/$2/$1");
    std::cout << replaced << std::endl; // 05/08/2026 01/09/2026
}

这里m.str(0)是完整日期,m.str(1)、m.str(2)、m.str(3)分别是年、月、日。regex_replace里的$1、$2、$3表示引用捕获分组,因此非常适合日期格式重排、字段脱敏和模板化替换。处理大文本前仍应评估表达式复杂度,避免过度回溯造成明显的运行时间增长。

  • std::sregex_iterator用于遍历全部匹配项
  • 可在循环中通过m.str(0)、m.str(1)等读取每次命中的完整结果和分组
  • std::regex_replace用于批量替换匹配内容
  • 替换字符串中的$1、$2、$3可直接引用对应捕获分组

错误处理与使用建议

构造std::regex时,如果表达式语法无效,标准库会抛出std::regex_error,因此动态表达式应放在异常处理代码中。下面是一个最小排错示例:

#include 
#include 
#include 

int main() {
    std::string pattern = "([A-Z]+";
    try {
        std::regex re(pattern);
    } catch (const std::regex_error& e) {
        std::cout << "regex error: " << e.what() << std::endl;
        std::cout << "error code: " << static_cast(e.code()) << std::endl;
    }
}

这个例子中的左括号没有闭合,构造阶段就会失败,因此需要在创建regex对象时立即捕获异常。e.what()可读取错误描述,e.code()可区分错误类别;如果表达式来自配置文件、用户输入或数据库,而不是写死在源码中,更应该在构造阶段处理失败路径。正则表达式适合结构清晰的文本规则,但不宜承担完整语法解析任务。对于固定前缀、单字符查找或简单分隔,普通字符串函数通常更直观,也可能具有更稳定的性能。实际使用时还应准备空字符串、边界长度、非法字符和未匹配分组等测试用例。

  • 捕获const std::regex_error&并读取what()code()
  • 动态表达式要在构造std::regex时处理失败
  • 优先选择清晰且回溯较少的表达式
  • 为边界输入和失败路径编写测试

掌握语法选项、匹配方式、分组读取、遍历替换和异常处理后,C++11正则表达式就能覆盖大多数常见文本任务。实际落地时应明确是否需要整串校验、首个命中还是全部命中,同时注意转义层次和构造阶段报错,这样代码会更容易维护和排查。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多