正则表达式

一、正则表达式基础

正则表达式(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;
    }

相关推荐
波波0072 小时前
每日一题:什么是强类型语言和弱类型语言?
开发语言
Chan162 小时前
LeetCode 热题 100 | 矩阵
java·开发语言·数据结构·算法·spring·java-ee·intellij-idea
码农多耕地呗2 小时前
java字符串转Integer方法(正则表达式)
java·正则表达式
钓鱼的肝2 小时前
[GESP-4.2503.T2]二阶矩阵
c++·算法·矩阵
小二·2 小时前
Go 语言系统编程与云原生开发实战(第39篇)
开发语言·云原生·golang
小小unicorn2 小时前
[微服务即时通讯系统]文件存储子服务的实现与测试
c++·redis·微服务·云原生·架构
笨笨马甲2 小时前
Qt的界面渲染体系
开发语言·qt
草莓熊Lotso2 小时前
MySQL 数据库基础入门:从概念到实战
linux·运维·服务器·数据库·c++·人工智能·mysql
05大叔2 小时前
Mybatis-Plus
java·开发语言·mybatis