C++ 中的正则表达式(Regular Expression)主要通过标准库 <regex>
提供,能够用于字符串匹配、查找、替换、验证格式等。它在 C++11 中首次引入,并在 C++14 和 C++17 中逐步完善。
一、头文件和命名空间
#include <regex>
#include <string>
#include <iostream>using namespace std;
二、主要类介绍
类名 | 功能描述 |
---|---|
std::regex | 用于存储正则表达式模式 |
std::smatch | 用于存储匹配结果(string 匹配) |
std::cmatch | 用于存储匹配结果(C字符串匹配) |
std::regex_match | 判断整个字符串是否匹配正则模式 |
std::regex_search | 判断字符串中是否有匹配正则的部分 |
std::regex_replace | 替换匹配的字符串内容 |
三、常见正则表达式语法
正则语法 | 含义 | |
---|---|---|
. | 匹配任意单个字符 | |
* | 匹配前面的字符 0 次或多次 | |
+ | 匹配前面的字符 1 次或多次 | |
? | 匹配前面的字符 0 次或 1 次 | |
^ | 匹配字符串开头 | |
$ | 匹配字符串结尾 | |
[] | 匹配方括号内任一字符 | |
` | ` | 或运算符 |
() | 子表达式分组 | |
\d | 数字 | |
\w | 单词字符(字母/数字/下划线) | |
\s | 空白字符 |
四、示例代码
1. 使用 regex_match
完全匹配
string s = "abc123";
regex pattern("[a-z]+\\d+"); // 小写字母 + 数字if (regex_match(s, pattern)) {cout << "完全匹配成功" << endl;
} else {cout << "匹配失败" << endl;
}
2. 使用 regex_search
局部匹配
string s = "hello 123 world";
regex pattern("\\d+"); // 匹配数字smatch result;
if (regex_search(s, result, pattern)) {cout << "找到数字:" << result.str() << endl;
}
3. 使用 regex_replace
字符替换
string s = "abc123xyz456";
regex pattern("\\d+"); // 匹配数字string replaced = regex_replace(s, pattern, "#");
cout << replaced << endl; // 输出:abc#xyz#
4. 捕获多个子匹配
string s = "Name: John, Age: 25";
regex pattern("Name: (\\w+), Age: (\\d+)");smatch match;
if (regex_search(s, match, pattern)) {cout << "姓名:" << match[1] << endl;cout << "年龄:" << match[2] << endl;
}
5. 匹配邮箱格式示例
string email = "user123@example.com";
regex pattern("[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}");if (regex_match(email, pattern)) {cout << "邮箱格式合法" << endl;
} else {cout << "邮箱格式错误" << endl;
}
五、匹配模式(flag)
正则对象可以设置模式:
regex pattern("abc", regex_constants::icase); // 忽略大小写
常用标志位:
标志名 | 含义 |
---|---|
regex_constants::icase | 忽略大小写 |
regex_constants::ECMAScript | 默认模式,支持现代语法 |
regex_constants::basic | 基本正则 |
regex_constants::extended | 扩展正则(如 POSIX) |
六、性能提示
regex
在 C++11 初期实现性能一般,现代编译器已优化。- 对于频繁匹配,可复用
std::regex
对象,避免重复构造。 - 若性能要求极高,可考虑
RE2
等替代库(Google)。
七、综合实战示例
下面以为 日志过滤、文件名匹配 和 表单验证 的完整 C++ 正则表达式示例,每个都附详细解释,帮助大家实际应用。
1、日志过滤:提取指定格式的日志(如错误信息)
目标:从日志中提取 [ERROR]
级别的信息
#include <iostream>
#include <regex>
#include <string>
#include <vector>using namespace std;int main() {vector<string> logs = {"[INFO] 2025-07-14 Connection established","[ERROR] 2025-07-14 Disk not found","[WARN] 2025-07-14 High memory usage","[ERROR] 2025-07-14 Timeout occurred"};regex error_pattern(R"(\[ERROR\]\s+(\d{4}-\d{2}-\d{2})\s+(.*))");for (const auto& log : logs) {smatch match;if (regex_match(log, match, error_pattern)) {cout << "日期: " << match[1] << ", 错误信息: " << match[2] << endl;}}return 0;
}
输出:
日期: 2025-07-14, 错误信息: Disk not found
日期: 2025-07-14, 错误信息: Timeout occurred
2、文件名匹配:匹配特定后缀的文件(如 .txt
、.log
)
#include <iostream>
#include <regex>
#include <vector>using namespace std;int main() {vector<string> filenames = {"report.txt", "data.csv", "log_2025.log", "notes.TXT", "script.cpp"};regex txt_log_pattern(R"((.*)\.(txt|log))", regex_constants::icase); // 忽略大小写cout << "匹配的文件名:" << endl;for (const auto& name : filenames) {if (regex_match(name, txt_log_pattern)) {cout << " " << name << endl;}}return 0;
}
输出:
匹配的文件名:report.txtlog_2025.lognotes.TXT
3、表单验证:验证邮箱、手机号、密码强度
1. 邮箱验证
string email = "test_user-123@example.co.uk";
regex email_pattern(R"([\w\.-]+@[\w\.-]+\.[a-zA-Z]{2,})");cout << (regex_match(email, email_pattern) ? "邮箱合法" : "邮箱非法") << endl;
2. 手机号验证(中国大陆)
string phone = "13812345678";
regex phone_pattern(R"(1[3-9]\d{9})"); // 以1开头 + 合法段位 + 9位数字cout << (regex_match(phone, phone_pattern) ? "手机号合法" : "手机号非法") << endl;
3. 密码强度验证(8~16位,包含字母和数字)
string password = "Abc12345";
regex pwd_pattern(R"((?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,16})");cout << (regex_match(password, pwd_pattern) ? "密码合法" : "密码不合法") << endl;
4、总结与推荐实践
场景 | 推荐正则 | |
---|---|---|
日志提取 | ^\[ERROR\].* 或带时间戳的模式 | |
文件筛选 | `.*.(txt | log)$` |
邮箱验证 | [\w\.-]+@[\w\.-]+\.[a-zA-Z]{2,} | |
手机号验证 | 1[3-9]\d{9} | |
密码验证 | (?=.*[A-Za-z])(?=.*\d).{8,16} |