正则表达式

一、正则表达式基础

正则表达式(Regular Expression,简称Regex/RE)是一种文本模式匹配工具,通过预定义的语法规则描述字符串的特征,用于快速检索、替换、验证符合特定规则的文本(如邮箱、手机号、URL等)。

1. 核心概念
  • 模式(Pattern):由正则语法组成的字符串,描述要匹配的文本规则;
  • 匹配(Match):检查目标字符串是否符合模式规则,或提取符合规则的子串;
  • 元字符 :正则的核心语法,具有特殊含义(如 *+|[] 等);
  • 普通字符:无特殊含义的字符(如字母、数字),匹配自身。
2. 常用正则语法(基础)
语法 含义 示例
^ 匹配字符串开头(多行模式下匹配行开头) ^abc 匹配 "abc123"
$ 匹配字符串结尾(多行模式下匹配行结尾) abc$ 匹配 "123abc"
. 匹配任意单个字符(除换行符 \n a.c 匹配 "abc"、"a1c"
* 匹配前面的字符/组 0次或多次 ab*c 匹配 "ac"、"abc"、"abbbc"
+ 匹配前面的字符/组 1次或多次 ab+c 匹配 "abc"、"abbbc"(不匹配"ac")
? 匹配前面的字符/组 0次或1次(非贪婪匹配) ab?c 匹配 "ac"、"abc"
{n} 匹配前面的字符/组 恰好n次 ab{2}c 匹配 "abbc"
{n,} 匹配前面的字符/组 至少n次 ab{2,}c 匹配 "abbc"、"abbbc"
{n,m} 匹配前面的字符/组 n到m次 ab{2,3}c 匹配 "abbc"、"abbbc"
[] 字符集:匹配括号内任意一个字符(- 表示范围,^ 表示取反) [a-z] 匹配小写字母,[^0-9] 匹配非数字
` ` 或:匹配 `
() 分组:将括号内的模式视为一个整体,可结合量词使用 (ab)+ 匹配 "ab"、"abab"
\d 匹配数字(等价于 [0-9] \d{3} 匹配 3位数字
\w 匹配字母、数字、下划线(等价于 [a-zA-Z0-9_] \w+ 匹配单词
\s 匹配空白字符(空格、制表符、换行符等) \s+ 匹配多个空格
\ 转义字符:匹配元字符本身(如 \. 匹配 ".",\* 匹配 "*") a\.b 匹配 "a.b"
3. 常用场景示例
  • 匹配手机号(11位,以1开头):^1\d{10}$
  • 匹配邮箱:^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$
  • 匹配整数(正负):^[-+]?\d+$

二、C++ 正则表达式匹配

C++11 及以上标准提供了 <regex> 库,支持正则表达式操作,核心类和函数如下:

1. 核心组件
组件 作用
std::regex 存储正则表达式模式(编译后的正则对象)
std::smatch 存储字符串匹配结果(针对 std::string
std::regex_match 完全匹配:检查整个字符串是否符合正则模式(返回 bool)
std::regex_search 部分匹配:查找字符串中第一个符合正则模式的子串(返回 bool)
std::regex_replace 替换:将字符串中符合正则模式的子串替换为指定内容
std::sregex_iterator 迭代器:遍历字符串中所有符合正则模式的子串
2. 关键注意事项
  • C++ 中反斜杠 \ 是转义字符,因此正则中的 \d 需写成 \\d(双反斜杠);
  • 正则模式编译可能抛出异常(如语法错误),建议用 try-catch 捕获;
  • 匹配模式(std::regex_constants::syntax_option_type):
    • std::regex::ECMAScript:默认模式,兼容 JavaScript 正则语法;
    • std::regex::icase:忽略大小写;
    • std::regex::multiline:多行模式(^/$ 匹配行开头/结尾)。

三、C++ 正则表达式实战示例

示例1:完全匹配(验证手机号)
cpp 复制代码
#include <iostream>
#include <string>
#include <regex>
using namespace std;

int main() {
    // 正则模式:11位手机号(以1开头,后接10位数字)
    // 注意:C++中需用\\d表示\d,而非\d
    regex phone_pattern("^1\\d{10}$", regex::ECMAScript);
    
    vector<string> phones = {"13800138000", "1234567890", "138001380001", "abc123456789"};
    
    for (const string& phone : phones) {
        bool is_match = regex_match(phone, phone_pattern);
        cout << "手机号:" << phone << " → " << (is_match ? "合法" : "非法") << endl;
    }
    
    return 0;
}

输出

复制代码
手机号:13800138000 → 合法
手机号:1234567890 → 非法
手机号:138001380001 → 非法
手机号:abc123456789 → 非法
示例2:部分匹配(提取字符串中的所有数字)
cpp 复制代码
#include <iostream>
#include <string>
#include <regex>
#include <iterator>
using namespace std;

int main() {
    string text = "小红有10个苹果,小明有20个梨,总共有30个水果。";
    // 正则模式:匹配任意数字(\\d+ 匹配1个或多个数字)
    regex num_pattern("\\d+");
    
    // 方式1:用 regex_search 找第一个匹配
    smatch match_result;
    if (regex_search(text, match_result, num_pattern)) {
        cout << "第一个数字:" << match_result.str() << endl; // 输出:10
    }
    
    // 方式2:用 sregex_iterator 遍历所有匹配
    cout << "所有数字:";
    sregex_iterator it(text.begin(), text.end(), num_pattern);
    sregex_iterator end_it; // 结束迭代器
    for (; it != end_it; ++it) {
        cout << (*it).str() << " "; // 输出:10 20 30
    }
    cout << endl;
    
    return 0;
}

输出

复制代码
第一个数字:10
所有数字:10 20 30 
示例3:替换(将所有空格替换为逗号)
cpp 复制代码
#include <iostream>
#include <string>
#include <regex>
using namespace std;

int main() {
    string text = "hello   world!  this is c++ regex";
    // 正则模式:匹配1个或多个空白字符(\\s+)
    regex space_pattern("\\s+");
    
    // 替换:将所有匹配的空格替换为逗号
    string result = regex_replace(text, space_pattern, ",");
    cout << "替换前:" << text << endl;
    cout << "替换后:" << result << endl;
    
    return 0;
}

输出

复制代码
替换前:hello   world!  this is c++ regex
替换后:hello,world!,this,is,c++,regex
示例4:分组匹配(提取邮箱的用户名和域名)
cpp 复制代码
#include <iostream>
#include <string>
#include <regex>
using namespace std;

int main() {
    string email = "test_123@example.com";
    // 正则模式:分组匹配用户名和域名(() 表示分组)
    regex email_pattern("^([a-zA-Z0-9_-]+)@([a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+)$");
    
    smatch match_result;
    if (regex_match(email, match_result, email_pattern)) {
        cout << "完整邮箱:" << match_result.str(0) << endl; // 第0组:整个匹配结果
        cout << "用户名:" << match_result.str(1) << endl;   // 第1组:用户名
        cout << "域名:" << match_result.str(2) << endl;     // 第2组:域名
    }
    
    return 0;
}

输出

复制代码
完整邮箱:test_123@example.com
用户名:test_123
域名:example.com

四、常见问题与注意事项

  1. 转义字符问题
    C++ 字符串中 \ 是转义符,因此正则中的 \d 需写成 \\d\. 需写成 \\.,避免语法错误;

  2. 完全匹配 vs 部分匹配

    • regex_match:要求整个字符串符合模式(如验证手机号、邮箱);
    • regex_search:只需字符串中存在子串符合模式(如提取数字);
  3. 性能优化
    频繁使用的正则模式建议提前编译为 std::regex 对象(避免重复编译);

  4. 异常处理
    非法正则语法会抛出 std::regex_error,建议捕获:

    cpp 复制代码
    try {
        regex invalid_pattern("^[a-z+"); // 语法错误(缺少])
    } catch (const regex_error& e) {
        cout << "正则语法错误:" << e.what() << endl;
    }

相关推荐
不知名。。。。。。。。3 分钟前
Qt常用控件
开发语言·qt
顾温17 分钟前
数据转换函数
开发语言·算法
·心猿意码·18 分钟前
C++ volatile 与 std::atomic 底层语义剖析
c++
一个人说晚安18 分钟前
Docker 部署 OpenClaw 并接入第三方大模型 (MiniMax) 完整排坑指南
java·开发语言·dubbo
Tanecious.22 分钟前
蓝桥杯备赛:Day1-奖学金
c语言·c++·蓝桥杯
汉克老师24 分钟前
GESP2025年6月认证C++三级( 第三部分编程题(1、奇偶校验)
c++·算法·gesp三级·gesp3级·按位操作
AI职业加油站24 分钟前
数据要素时代:大数据治理工程师证书深度解码
大数据·开发语言·人工智能·python·数据分析
CoderCodingNo24 分钟前
【GESP】C++八级考试大纲知识点梳理 (8) 算法优化技巧
开发语言·c++
We་ct43 分钟前
LeetCode 295. 数据流的中位数:双堆解法实战解析
开发语言·前端·数据结构·算法·leetcode·typescript·数据流
十年编程老舅1 小时前
窥探内核心脏:深入解析 proc 虚拟文件系统
linux·服务器·数据库·c++·linux内核·文件系统·读写锁