C++: 正则表达式

最后更新:2026-08-26

第41课我们学了文件操作。

现在,我们要学正则表达式——文本处理的"瑞士军刀"。

验证邮箱、提取电话号码、替换文本……正则表达式为这一切提供了简洁的方案。


1. 正则表达式概述

(1) 1.1 什么是正则表达式?

正则表达式(Regex)是一种文本模式描述语言,用于匹配、查找、替换文本。

生活类比:


(2) 1.2 C++正则表达式库

C++11引入了正则表达式支持,在 regex 头文件中。

四个主要函数:

函数 功能
std::regex_match 完全匹配
std::regex_search 查找
std::regex_replace 替换
std::regex_iterator 迭代查找


2. 基本匹配

(1) 2.1 regex_match——完全匹配

示例:验证手机号(难度⭐)

▶ 示例 1:正则表达式应用(难度⭐)

CPP
#include <iostream>
#include <regex>
#include <string>

int main() {
 std::string phone = "13812345678";
 std::regex pattern("^1[3-9]\\d{9}$"); // 手机号正则
 
 if (std::regex_match(phone, pattern)) {
 std::cout << "有效的手机号" << std::endl;
 } else {
 std::cout << "无效的手机号" << std::endl;
 }
 
 return 0;
}
▶ 试一试

输出:

TEXT 📖 仅展示
有效的手机号
无效的手机号

运行结果:

TEXT 📖 仅展示
有效的手机号

(2) 2.2 正则表达式语法

符号 说明 示例
. 任意字符 a.c 匹配 abc
^ 开头 ^abc 匹配以abc开头
$ 结尾 abc$ 匹配以abc结尾
* 0次或多次 a* 匹配 aaa
+ 1次或多次 a+ 匹配 aaa
? 0次或1次 a? 匹配 a 或 ``
{n} 恰好n次 a{3} 匹配 aaa
[abc] 字符集 [abc] 匹配 abc
[^abc] 非字符集 [^abc] 匹配除abc外的字符
\d 数字 \d 匹配 0-9
\w 单词字符 \w 匹配 a-zA-Z0-9_


3. 查找和替换

(1) 3.1 regex_search——查找

示例:查找邮箱(难度⭐⭐)

CPP
#include <iostream>
### ▶ 示例 2:正则表达式应用(难度⭐)

#include <regex>
#include <string>

int main() {
 std::string text = "联系我:abc@example.com 或 test@gmail.com";
 std::regex pattern("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}");
 
 std::smatch match;
 if (std::regex_search(text, match, pattern)) {
 std::cout << "找到邮箱:" << match[0] << std::endl;
 }
 
 return 0;
}

(2) 3.2 regex_replace——替换

示例:隐藏手机号中间四位(难度⭐⭐)

CPP
#include <iostream>
#include <regex>
#include <string>

int main() {
 std::string phone = "13812345678";
 std::regex pattern("(\\d{3})\\d{4}(\\d{4})");
 
 std::string result = std::regex_replace(phone, pattern, "$1****$2");
 std::cout << "隐藏后:" << result << std::endl;
 
 return 0;
}

运行结果:

TEXT 📖 仅展示
隐藏后:138****5678


4. 迭代查找

(1) 4.1 regex_iterator

示例:找出所有邮箱(难度⭐⭐⭐)

CPP
#include <iostream>
#include <regex>
#include <string>

int main() {
 std::string text = "联系我:abc@example.com 或 test@gmail.com";
 std::regex pattern("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}");
 
 auto begin = std::sregex_iterator(text.begin(), text.end(), pattern);
 auto end = std::sregex_iterator();
 
 std::cout << "找到的邮箱:" << std::endl;
 for (auto it = begin; it != end; ++it) {
 std::cout << it->str() << std::endl;
 }
 
 return 0;
}

运行结果:

TEXT 📖 仅展示
找到的邮箱:
abc@example.com
test@gmail.com


5. 分组和捕获

(1) 5.1 分组

用括号 () 创建分组,可以提取子串

示例:提取日期(难度⭐⭐)

CPP
#include <iostream>
#include <regex>
#include <string>

int main() {
 std::string date = "2026-06-28";
 std::regex pattern("(\\d{4})-(\\d{2})-(\\d{2})");
 
 std::smatch match;
 if (std::regex_match(date, match, pattern)) {
 std::cout << "年:" << match[1] << std::endl;
 std::cout << "月:" << match[2] << std::endl;
 std::cout << "日:" << match[3] << std::endl;
 }
 
 return 0;
}

运行结果:

TEXT 📖 仅展示
年:2026
月:06
日:28


6. 常见应用场景

(1) 6.1 验证输入

场景 正则表达式
邮箱 [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
手机号 ^1[3-9]\d{9}$
身份证 ^\d{17}[\dXx]$
IP地址 ^(\d{1,3}\.){3}\d{1,3}$

(2) 6.2 提取信息

示例:从HTML提取链接(难度⭐⭐⭐)

CPP
#include <iostream>
#include <regex>
#include <string>

int main() {
 std::string html = "<a href=\"https://example.com\">Example</a>";
 std::regex pattern("<a href=\"([^\"]+)\"");
 
 std::smatch match;
 if (std::regex_search(html, match, pattern)) {
 std::cout << "链接:" << match[1] << std::endl;
 }
 
 return 0;
}

▶ 示例 3:验证邮箱格式(难度⭐)

CPP
#include <iostream>
#include <regex>
#include <string>

bool isValidEmail(const std::string& email) {
    std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");
    return std::regex_match(email, pattern);
}

int main() {
    std::string emails[] = {"test@example.com", "invalid-email", "user.name@domain.org"};

    for (const auto& email : emails) {
        if (isValidEmail(email)) {
            std::cout << email << " -> 有效" << std::endl;
        } else {
            std::cout << email << " -> 无效" << std::endl;
        }
    }

    return 0;
}
▶ 试一试

输出:

TEXT 📖 仅展示
 -> 有效
 -> 无效

❓ 常见问题

Q 正则表达式很慢怎么办?
A - 编译一次,多次使用(std::regex 构造函数很慢) - 用 std::regex_constants::optimize 标志

Q:转义字符太多怎么办? A:用原始字符串字面量(C++11):

CPP
// 难读
std::regex pattern("\\\\d+");

// 好读
std::regex pattern(R"(\d+)");

Q 正则表达式能处理所有文本吗?
A 不能。HTML/XML等用正则解析很复杂,建议用专门的解析器。

📖 小节

知识点 要点
regex_match 完全匹配
regex_search 查找
regex_replace 替换
regex_iterator 迭代查找
分组 () 提取子串

📝 作业

  1. **基础题 (Difficulty ⭐):用 std::regex 判断一个字符串是否匹配"纯数字"模式(^\d+$),测试 "123"、"12a3"、"abc"。

  2. **进阶题 (Difficulty ⭐⭐):用 regex_search 从一段文本中提取所有邮箱地址(匹配 \w+@\w+\.\w+ 模式)。

  3. 挑战题 (Difficulty ⭐⭐⭐):用 regex_replace 实现一个"敏感词过滤"函数——将文本中的指定敏感词替换为 *。支持多个敏感词。



下一课:多线程基础(#43)

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏