c++oding="utf-8" ?>
std::regex_match要求整个字符串完全匹配,用于格式校验;std::regex_search查找子串匹配,适用于提取邮箱、手机号等片段;提取捕获组需用std::smatch,检查返回值后通过match[1].str()获取第一个捕获组。

std::regex_match 和 std::regex_search 有什么区别?
std::regex_match 要求整个输入字符串完全匹配正则模式,哪怕多一个空格都不行;std::regex_search 只要找到子串匹配就返回 true,更常用在提取场景。
- 提取邮箱、手机号、日期等片段时,几乎总是用
std::regex_search -
std::regex_match更适合做格式校验(比如验证输入是否为合法 IPv4 地址) - 两者都需配合
std::smatch使用才能拿到捕获组内容,直接用std::string::find是拿不到分组的
怎么安全地提取第一个捕获组?
用 std::smatch 接收匹配结果,索引 [0] 是全匹配,[1] 是第一个括号内的捕获组:
std::string text = "Order ID: #12345, status: shipped";
std::regex re(R"(#(\d+))");
std::smatch match;
if (std::regex_search(text, match, re)) {
std::string id = match[1].str(); // → "12345"
}
- 必须检查
std::regex_search返回值为true,否则访问match[1]是未定义行为 -
match[n].str()返回的是std::string拷贝,不是视图,不用担心生命周期问题 - 如果正则没写括号(比如
R"(\d+)"),match[1]会越界,得用match[0]取整个匹配
提取多个匹配怎么办?
用循环调用 std::regex_search,每次从上一次结束位置继续:
std::string text = "price: $19.99, discount: $3.50, total: $16.49";
std::regex re(R"(\$(\d+\.\d{2}))");
std::smatch match;
std::string::const_iterator it = text.cbegin();
while (std::regex_search(it, text.cend(), match, re)) {
std::cout
- 忘记更新
it会导致无限循环,这是最常踩的坑 -
match[0].first和match[0].second是迭代器,对应匹配起止位置 - 不要用
std::sregex_iterator—— 它内部也依赖相同逻辑,但错误处理更隐蔽,调试困难
为什么我的正则总不匹配?常见陷阱
C++ 的 std::regex 默认使用 ECMAScript 语法,但不支持很多现代特性(比如 lookbehind、\K),而且转义容易出错:
- 原始字符串字面量
R"(...)"是必须的,否则反斜杠要写成"\d",极易漏掉 -
std::regex在某些标准库实现(如 libstdc++)中性能差、功能残缺,Clang + libc++ 或 MSVC 更可靠 - 想匹配点号
.?得写成R"(.)",写成"."会匹配任意字符 - 多行文本中想让
^和$匹配每行首尾?需要加std::regex_constants::multiline标志,但该标志在 libstdc++ 中无效
实际项目里,如果正则复杂或性能敏感,建议改用 boost::regex 或 RE2,标准库的 std::regex 真的不太稳。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











