C++11之正则表达式使用指南--[正则表达式介绍]|[regex的常用函数等介绍]

介绍之前,我们先来一个非常简单的使用例子,先见一见

cpp 复制代码
#include<iostream>
#include<string>
#include<regex>

int main()
{
    std::string str = "/number/1234";
    std::regex e("/numbers/(\\d+)");
    std::smatch matches;

    bool ret = std::regex_match(str,matches,e);
    if(ret)
    for(auto &s:matches)
    {
        std::cout<<s<<std::endl;
    }
    return 0;
}

我们本文分为两部分:1.正则表达式的基本语法 2.C++种regex的使用

建议:我们的基础语法不用死记,大家记住常用的就行了

一.正则表达式的基础语法

1)锚点(边界匹配)

锚点不匹配具体字符,而是匹配字符串的位置,用于限定匹配发生的位置。

语法 含义 例子说明
^(常用) 匹配字符串开头 ^Hello → 仅匹配以 Hello 开头的字符串
$(常用) 匹配字符串结尾 World$ → 仅匹配以 World 结尾的字符串
\b 匹配单词边界(单词字符与非单词字符之间) \bcat\b → 匹配独立单词 cat,不匹配 category
\B 匹配非单词边界 \Bcat\B → 匹配 category 中的 cat,不匹配独立的 cat

示例:

cpp 复制代码
#include <iostream>
#include <regex>
#include <string>

using namespace std;

int main() {
    string text = "I have a cat and a category";
    regex pattern(R"(\bcat\b)"); // 匹配独立的 "cat"
    
    // 搜索所有匹配(用 sregex_iterator)
    sregex_iterator it(text.begin(), text.end(), pattern);
    sregex_iterator end;
    
    for (; it != end; ++it) {
        cout << "匹配到: " << it->str() << endl;
    }
    // 输出:匹配到: cat(仅匹配独立单词,不匹配 category 中的 cat)
    return 0;
}

2)字符类匹配

定义一个字符集合,匹配集合中的任意一个字符

1. 基础形式(基本都常用)

语法 含义 例子
[abc] 匹配 abc 中的任意一个 gr[ae]y → 匹配 graygrey
[a-z] 匹配 az 之间的任意小写字母 [a-z]+ → 匹配连续小写字母
[A-Z] 匹配 AZ 之间的任意大写字母 [A-Z]{2} → 匹配连续两个大写字母
[0-9] 匹配 09 之间的任意数字 [0-9]{3} → 匹配连续 3 个数字
[a-zA-Z0-9] 匹配任意字母或数字 [a-zA-Z0-9]+ → 匹配连续的字母 / 数字

2. 排除型字符类(常用)

语法 含义 例子
[^abc] 匹配除 abc 外的任意字符 [^0-9] → 匹配任意非数字字符
[^a-z] 匹配除小写字母外的任意字符 [^a-zA-Z] → 匹配任意非字母字符

3. 预定义字符类(前面几个我经常用)

注意:这里由于是\d在我们c++进行编写的时候,为了/的完整性我们要//d才能表现出/d,这里我们可以用c++11的原始字符串语法,也就是R"()",比如cout<< R"(\d)"

简写 含义 等价写法
\d 匹配任意数字 [0-9]
\w 匹配任意 "单词字符"(字母、数字、下划线) [a-zA-Z0-9_]
\s 匹配任意 "空白字符"(空格、制表符 \t、换行符 \n 等) [ \t\n\r\f\v]
\D 匹配任意非数字字符 [^0-9]
\W 匹配任意非单词字符 [^a-zA-Z0-9_]
\S 匹配任意非空白字符 [^ \t\n\r\f\v]

3)量词

控制前面的字符 / 字符类 / 分组重复出现的次数。

1.基础量词

语法 含义 例子说明
{n} 精确重复 n \d{4} → 匹配连续 4 个数字(如 2026
{n,} 至少重复 n \d{2,} → 匹配连续 2 个或更多数字
{n,m} 重复 nm 次(含 nm \d{2,4} → 匹配连续 2-4 个数字
+ 至少重复 1 次(等价 {1,} \d+ → 匹配 1 个或多个连续数字
* 重复 0 次或多次(等价 {0,} \d* → 匹配 0 个或多个数字(允许空)
? 重复 0 次或 1 次(等价 {0,1},表示 "可选") colou?r → 匹配 colorcolour

2. 贪婪 vs 非贪婪匹配

量词默认是贪婪的 (尽可能多匹配);在量词后加 ? 可变为非贪婪的(尽可能少匹配)。

贪婪模式 非贪婪模式 区别(以字符串 "a123b456b" 为例)
a.*b a.*?b 贪婪:匹配 a123b456b(从第一个 a 到最后一个 b)非贪婪:匹配 a123b(从第一个 a 到第一个 b

4)分组与捕获(捕获对象到smatch)

1. 捕获分组

匹配并捕获分组内容,可通过 smatch[n] 在 C++ 中提取。

例如:提取日期中的年、月、日

cpp 复制代码
#include <iostream>
#include <regex>
#include <string>

using namespace std;

int main() {
    string date = "2026-03-27";
    regex pattern(R"((\d{4})-(\d{2})-(\d{2}))"); // 3个捕获分组:年、月、日
    smatch result;
    
    if (regex_match(date, result, pattern)) {
        cout << "完整匹配: " << result[0] << endl; // 2026-03-27(第0组是完整匹配)
        cout << "年: " << result[1] << endl;         // 2026(第1组)
        cout << "月: " << result[2] << endl;         // 03(第2组)
        cout << "日: " << result[3] << endl;         // 27(第3组)
    }  
    return 0;
}

5)选择分支

| 表示 "或" 关系,匹配 | 左边或右边的正则表达式,其实简单来说,就是匹配任意一个

例如:

cpp 复制代码
(GET|HEAD|POST|PUT|DELETE) //捕获任意一个

6)转义字符

如果需要匹配正则中的特殊字符 (如 . ``* ``? ``+ ``( ``) ``[ ``] ``{ } ``^ ``$ ``\ ``| 等),需在前面加 \ 进行转义。

但是这里之前介绍过我们可以用c++11的R"()"----原始字符串的语法,从而不用考虑是否是特殊字符

7)补充:任意字符 .

. 匹配除换行符 \n 外的任意一个字符

  • 例子:a.c → 匹配 abca1ca!c 等(ac 之间有任意一个字符);
  • 若需匹配包括换行符在内的任意字符,可用 [\s\S](空白 + 非空白,覆盖所有字符)。

8)语法优先级总结(从高到低)

  1. 转义字符:\
  2. 括号:()(?:)[]
  3. 量词:*+?{n}{n,}{n,m}
  4. 锚点:^$
  5. 选择分支:|

9)C++ 正则使用的核心建议

  • 优先用原始字符串 R"()" :避免手动转义 \,代码更清晰;
  • 复用 std::regex 对象:正则编译开销大,避免在循环中重复构造;
  • 异常处理 :正则语法错误会抛 std::regex_error,建议用 try-catch 包裹;

二、C++<regex>介绍

C++ 从 C++11 开始通过标准库 <regex> 提供正则表达式支持,涵盖匹配、搜索、替换和分组捕获等功能。

我们可以平常工作用来匹配对应字符等等,其实竞赛感觉也可以用,因为我记得之前pta的题经常有这种非常恶心的匹配,替换的题目

1、主要类:

类名 用途说明
std::regex 正则表达式对象,用于存储编译后的正则模式。
std::smatch 匹配结果容器(针对 std::string),存储子匹配(分组)信息。

2、核心函数详解

1). std::regex_match:全字符串匹配

函数原型:

cpp 复制代码
bool regex_match(const std::string& s, const std::regex& re);
bool regex_match(const std::string& s, std::smatch& m, const std::regex& re);

参数

  • s:待匹配的字符串。
  • restd::regex 对象(编译后的正则表达式)。
  • m(可选):std::smatch 对象,用于存储匹配结果和分组信息。

返回值bool,表示是否完全匹配。

2). std::regex_search:子串搜索匹配

在字符串中搜索第一个匹配的子串(无需全匹配)。

函数原型

cpp 复制代码
bool regex_search(const std::string& s, const std::regex& re);
bool regex_search(const std::string& s, std::smatch& m, const std::regex& re);

参数 :同 regex_match

返回值bool,表示是否找到匹配。

3). std::regex_replace:替换匹配内容

将字符串中所有匹配的子串替换为指定格式。

函数原型

cpp 复制代码
std::string regex_replace(const std::string& s, const std::regex& re, const std::string& fmt);

参数

  • s:原字符串。
  • restd::regex 对象。
  • fmt:替换格式字符串,支持 $1$2 等引用分组内容。

返回值:替换后的新字符串。

3、常见使用场景代码示例

场景:输入验证(如手机号、邮箱)

cpp 复制代码
#include <iostream>
#include <regex>
#include <string>

using namespace std;

int main() {
    // 验证手机号(1开头,第二位3-9,共11位)
    string phone = "13812345678";
    regex phone_pattern(R"(^1[3-9]\d{9}$)");
    if (regex_match(phone, phone_pattern)) {
        cout << "手机号格式正确" << endl;
    } else {
        cout << "手机号格式错误" << endl;
    }

    // 验证邮箱(简单示例,非严格RFC标准)
    string email = "test@example.com";
    regex email_pattern(R"(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)");
    if (regex_match(email, email_pattern)) {
        cout << "邮箱格式正确" << endl;
    }

    return 0;
}
相关推荐
比昨天多敲两行4 小时前
C++ 二叉搜索树
开发语言·c++·算法
Tisfy4 小时前
LeetCode 2839.判断通过操作能否让字符串相等 I:if-else(两两判断)
算法·leetcode·字符串·题解
问好眼4 小时前
《算法竞赛进阶指南》0x04 二分-1.最佳牛围栏
数据结构·c++·算法·二分·信息学奥赛
海海不瞌睡(捏捏王子)4 小时前
C++ 知识点概要
开发语言·c++
会编程的土豆4 小时前
【数据结构与算法】优先队列
数据结构·算法
minji...6 小时前
Linux 进程信号(二)信号的保存,sigset_t,sigprocmask,sigpending
linux·运维·服务器·网络·数据结构·c++·算法
罗湖老棍子6 小时前
最大数(信息学奥赛一本通- P1549)(洛谷-P1198)
数据结构·算法·线段树·单点修改 区间求最大值
小O的算法实验室8 小时前
2026年KBS,赏金猎人优化算法+多无人机移动边缘计算与路径规划,深度解析+性能实测
算法·无人机·边缘计算
用户5671504710218 小时前
OpenClaw 记忆管理系统技术文档
算法