快速入门C++正则表达式

正则表达式(Regular Expression,简称 Regex)是一种强大的文本处理工具,广泛用于字符串的搜索、替换、分析等操作。它基于一种表达式语言,使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。正则表达式不仅在各种编程和脚本语言中被广泛支持,还是很多文本编辑器和处理工具的重要功能。

当需要从一堆字符串中提取出(或者是替换掉)具有一定规则(规律)的子字符串,那么用正则表达式会非常简单。

语法介绍

特殊字符

特殊字符在正则表达式中的作用是非常重要的,可以定义一系列的匹配规则。

.
  • 描述

匹配除换行符(\n)外的任意单个字符。
如果要匹配.字符,请用\.

注意:

  1. [.]内的.匹配的是.而不是任意单个字符
  2. (.)内的.匹配的是任意单个字符,而不是.
  • 示例
  1. a.c匹配的是abcacc等,但无法匹配ac
  2. [a.c]匹配的是a.c,但无法匹配abc
*
  • 描述

匹配前面子表达式任意多次(包含0次)。
如果要匹配*字符,请用\*

注意:

  1. 子表达式的意思是可以单独拎出来作为正则表达式的字符串
  2. 在匹配时必须保证*的前面有子表达式
  3. [*]内的*匹配的是*字符
  • 示例
  1. ab*c匹配的是acabcabbbbc等。(这里的子表达式是b
  2. [abc]*匹配的是 abcacacbabcc等。(这里的子表达式是[abc])
  3. (abc)*匹配的是 abcabcabcabcabcabc等。(这里的子表达式是(abc)
  4. [a*c]匹配的是a*c。(这里不做量化字符)

^
  • 描述

^字符的匹配规则有两种:

  1. 在方括号[]内时,匹配不包含在方括号内的单个字符
  2. 不在方括号内时,匹配字符串中的起始位置(起始位置也可以匹配)
  • 示例
  1. ^abc的匹配项有起始位置abc

比如输入字符串abc is abcd中匹配的是最前面的abc,最后面的无法匹配。

  1. [^abc]匹配的是除了abc这三个字符外的所有其他单个字符

[ ]
  • 描述

匹配方括号内包含的单个字符。

注意:

  1. 方括号内的-字符如果是第一个或最后一个的字符,那么它就是匹配-字符
  2. 方括号内的-字符不是第一个也不是最后一个字符,那么它就是匹配一个范围
  3. 如果方括号内的第一个字符是]会把最前面的[]当做子表达式
  • 示例
  1. [abc]的匹配项有abc
  2. [a-z]的匹配项是a-z的范围,即匹配的是a-z的所有小写字母。
  3. [abcx-z]的匹配项有abc以及x-z的范围
  4. [-abc]的匹配项有-abc
  5. [abc-]的匹配项有abc-
  6. []abc]的匹配项有[]空字符集abc]
  7. []abc[]的匹配项有[]空字符集abc[]空字符集

$
  • 描述

$字符的匹配规则有两种:

  1. 在方括号[]内时,就是匹配$字符
  2. 不在方括号内时,匹配字符串的结束位置
  • 示例
  1. abc$的匹配项有abc结束位置

比如输入字符串abcd is abc中匹配的是最后的abc(结束位置不可见)

  1. [abc$]的匹配项有abc$

( )
  • 描述

圆括号的主要作用是定义一个子表达式,并设置捕获组。

捕获组(分组捕获)的主要作用是匹配组内的子表达式,并将匹配上的内容记录下来。
这导致使用捕获组的正则表达式的效率降低。

如果要匹配()字符,请使用\(\)
后面章节详细介绍。

+
  • 描述

匹配前面子表达式一次或零次。
如果要匹配+字符,请用\+

注意:

  1. 子表达式的意思是可以单独拎出来作为正则表达式的字符串
  2. 在匹配时必须保证+的前面有子表达式
  3. [+]内的+匹配的是+字符
  • 示例
  1. ab+c匹配的是abcabbcabbbc等,但不匹配ac。(这里的子表达式是b
  2. [abc]+匹配的是abcacacb等,但不匹配 。(这里的子表达式是[abc])
  3. (abc)+匹配的是abcabcabcabcabcabc等,但不匹配 。(这里的子表达式是(abc)
  4. [a+c]匹配的是a+c。(这里不做量化字符)

?
  • 描述

匹配前面子表达式0次或1次。
如果要匹配?字符,请用\?

  • 示例
  1. ab?c匹配的是acabc。(这里的子表达式是b
  2. [ab?c]匹配的是ab?c。(这里不做量化字符)

\
  • 描述

反斜杠主要起转义字符的作用,这里的转义是双向的(原义转特殊,特殊转原义)。

  • 原义转特殊
  1. \t表示制表符(Tab)
  2. \r表示回车符
  3. \n表示换行符
  4. \f表示换页符,用于打印文档中的换页
  5. \s表示任何空白字符,比如空格、制表符、回车符、换行符、换页符等
  6. \S表示非空白字符
    • 特殊转原义

所有量词(*+?{})的前面加\后,转义称为普通字符。

|
  • 描述

匹配|前面的子表达式或者|后面的子表达式(二选一,只要匹配上一个就算成功)。

  • 示例
  1. ab|c的匹配项是ab 或 c,能匹配上abc
  2. [ab]|c能匹配上abc

{ }
  • 描述

{ }也是一个量词,表示匹配前面的子表达式的次数(或次数范围)。
{ }有三种规范:

  1. {n}:表示匹配前面子表达式n次,n是一个非负整数(大于等于0的整数)
  2. {n,}:表示至少匹配前面子表达式n次,它是一个范围(大于等于n的整数),这里的n是一个非负整数
  3. {n,m}:表示至少匹配前面子表达式n次,最多匹配m次,且n<=m,这里的n和m都是非负整数
  • 示例
  1. abc{0}的匹配项是ab,这里的子表达式是c
  2. abc{2}的匹配项是abcc,这里的子表达式是c
  3. abc{2,}的匹配项是abccabcccabcccc
  4. abc{2,4}的匹配项是abccabccc以及abcccc
  5. (abc){2}的匹配项是abcabc
  6. [abc]{2}的匹配项是aaabacbabbbccacb以及cc

量化字符(量词)

量化字符是用来指定子表达式连续出现多少次才能匹配上。包含*+?{},具体细节看上面特殊字符章节。

定位字符

定位字符是匹配字符串中特殊的位置,比如字符串的首和尾。
定位字符包含:

  • ^

上面已经介绍了,这里就不介绍了。

  • $

上面已经介绍了,这里就不介绍了。

  • \b

匹配一个单词的边界,就是字符和空格之间的位置。比如:
a cat in cats字符串中,\bcat\b只能匹配到前面的cat,但后面的cats中的cat无法匹配。

  • \B

匹配非单词边界,比如:
a cat in cats字符串中,\bcat\B只能匹配到后面的cats中的cat,但前面的cat无法匹配。

扩展语法

速记字符

  • \d

匹配单个数字字符。

  • \w

匹配单个“单词字符”(字母数字字符加下划线)。
\w+可以匹配用户名。

  • \s

匹配空白字符,比如空格、制表符、回车符、换行符、换页符等。

反向引用

反向引用指的是通过\n(这里的n表示数字,一般支持1-9,有些标准也支持9以上)来引用对应捕获组所匹配到的内容。
比如t1_t2_t3_t3_t2_t1字符串是能够被(..)_(..)_(..)_\3_\2_\1这样的正则完全匹配的,它的引用流程如下图:
未命名文件.png

不同的语言底层实现的原理不一样。
存储捕获组的队列中下标0一般用来存储匹配成功的完整的字符串,示例中下标0位置存储的字符串应该是:
t1_t2_t3_t3_t2_t1

非捕获组

通过()实现的捕获组会影响性能,如果既要使用() 来进行分组,又不想作为捕获组被保存,所以需要使用非捕获组。
通过(?:..)可以实现非捕获组,示例如下:
还是用上面的示例:t1_t2_t3_t3_t2_t1字符串能够被(?:..)_(..)_(..)_\2_\1_t1完全匹配,其中(?:..)作为非捕获组匹配输入字符串的t1,不会被存储下来;然后后面在引用捕获组时,因为前面只有两个捕获组,所以引用计数最大是2。

C++中的正则表达式

C++11正式引入了正则表达式。

C++相关类和接口介绍

std::regex

std::regex是用于表示正则表达式的类,管理正则表达式。

std::regex_match

std::regex_match是一个函数,用于检查整个字符串是否完全符合正则表达式的模式。

需要整个字符串完全符合正则表达式,否则匹配失败。

std::regex_search

std::regex_search是一个函数,用于在字符串中搜索与正则表达式匹配的部分。

std::regex_iterator

std::regex_iterator迭代器用于迭代所有符合正则表达式的匹配项。

std::regex_iterator是一个模板类,根据字符类型的区别衍生出以下:
cregex_iteratorwcregex_iteratorsregex_iteratorwsregex_iterator

示例:

// 对于 std::string
std::string s = "Example string";
std::regex re("E");
std::sregex_iterator it(s.begin(), s.end(), re), end;
for (; it != end; ++it) {std::cout << it->str() << std::endl;
}// 对于 std::wstring
std::wstring ws = L"Example wstring";
std::wregex wre(L"E");
std::wsregex_iterator wit(ws.begin(), ws.end(), wre), endw;
for (; wit != endw; ++wit) {std::wcout << wit->str() << std::endl;
}

std::regex_replace

std::regex_replace是一个函数,用于替换与正则表达式匹配的子串。

std::regex_token_iterator

std::regex_token_iterator迭代器用于分割字符串,基于正则表达式找到的匹配项或非匹配项。

std::regex_error

std::regex_error是一个异常处理类,用于报告正则表达式中的错误。

try {// 使用正则表达式
} catch (const std::regex_error& e) {// 处理正则表达式错误
}

实际应用场景代码

匹配文本

#include <regex>
#include <iostream>int main() {std::string text = "This is a regular expression example.";std::regex pattern("regular expression");if (std::regex_search(text, pattern)) {std::cout << "The pattern was found in the text." << std::endl;} else {std::cout << "The pattern was not found in the text." << std::endl;}return 0;
}

查找文本位置

#include <regex>
#include <iostream>int main() {std::string text = "This is a regular expression example. ""Another example of regular expression.";std::regex pattern("example");std::smatch match;std::regex_search(text, match, pattern);if (match.size() > 0) {std::cout << "The first match was found at position " << match.position() << std::endl;std::cout << "The matched text is: " << match[0] << std::endl;} else {std::cout << "The pattern was not found in the text." << std::endl;}return 0;
}

替换文本

#include <regex>
#include <iostream>int main() {std::string text = "This is a regular expression example. ""It contains some outdated terms.";std::regex pattern("outdated");std::string replaced_text = std::regex_replace(text, pattern, "modern");std::cout << "The replaced text is: " << replaced_text << std::endl;return 0;
}

分组匹配

#include <regex>
#include <iostream>int main() {std::string text = "This is a regular expression example (123) 456-7890";std::regex pattern("(([^ ]+) (\\d{3})-(\\d{4}))$");std::smatch match;std::regex_search(text, match, pattern);if (match.size() > 0) {std::cout << "The first match was found at position " << match.position() << std::endl;std::cout << "Group 1: " << match[1] << std::endl;std::cout << "Group 2: " << match[2] << std::endl;std::cout << "Group 3: " << match[3] << std::endl;std::cout << "Group 4: " << match[4] << std::endl;} else {std::cout << "The pattern was not found in the text." << std::endl;}return 0;
}
#include <regex>
#include <iostream>int main() {std::string text = "(123) 456-7890";std::regex pattern("(([^ ]+) (\\d{3})-(\\d{4}))$");std::smatch match;if (std::regex_match(s, match, r)) {std::cout << "Group 1: " << match[1] << std::endl;std::cout << "Group 2: " << match[2] << std::endl;std::cout << "Group 3: " << match[3] << std::endl;std::cout << "Group 4: " << match[4] << std::endl;}return 0;
}

资料

推荐两个学习使用正则表达式的网站:

  1. https://regexper.com/
    可以直观地理解正则表达式的逻辑:
    在这里插入图片描述
  2. https://regexr.com
    通过该网站可以测试正则表达式的效果,并直观地看到匹配项:
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/22269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

堆盘子00

题目链接 堆盘子 题目描述 注意点 SetOfStacks应该由多个栈组成&#xff0c;并且在前一个栈填满时新建一个栈 解答思路 将多个栈存储到一个List中&#xff0c;当入栈时&#xff0c;如果List中最后一个栈容量已经达到cap&#xff0c;则需要新建一个栈&#xff0c;将元素推到…

springboot新生宿舍选取小程序-计算机毕业设计源码56499

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;新生宿舍选取小程序管理系统被用户普遍使用&#xff0c;为…

QT 篇 五、手把手教学用QT编写TCP上位机并显示温湿度

QT应用篇 一、QT上位机串口编程 二、QML用Image组件实现Progress Bar 的效果 三、QML自定义显示SpinBox的加减按键图片及显示值效果 四、window编译LibModbus库并用QT编写一个Modbus主机 五、手把手教学用QT编写TCP上位机并显示温湿度 文章目录 QT应用篇软件篇1.新建QT工程2.U…

PW1558A规格探秘:为何它是电源系统不可或缺的6A双向保护芯片?

描述 PW1558A 是一款先进的 28V 6A 额定双向负载开关&#xff0c; 提供过载、 短路、 输入电压浪涌、 过大冲击电流和过热保护&#xff0c; 为系统供电。 内置的 24mΩ超低 RDS(ON)电源开关有助于减少正常操作期间的功率损耗。 该设备具有两个输入/输出端口 VBUS1 和 VBUS2&…

实验11 OSPF协议配置

实验11 OSPF协议配置 一、OSPF单区域配置&#xff08;一&#xff09;原理描述&#xff08;二&#xff09;实验目的&#xff08;三&#xff09;实验内容&#xff08;四&#xff09;实验配置&#xff08;五&#xff09;实验步骤 二、OSPF多区域配置&#xff08;一&#xff09;原理…

5252DE 5G 外场通信测试仪

5252DE 5G 外场通信测试仪 集先进算法和高性能硬件于一体的便携式测试仪表 产品综述 5252DE 5G 外场通信测试仪是集合高性能频谱处理模块、多制式解析算法软件于一体的手持式测试仪表&#xff0c;具有很好的便携性、兼容性与可拓展性。 5252DE 具有工作频段宽、性能指标高…

SOLIDWORKS修改零件时出现错误怎么办?

我们在使用SOLIDWOKRS进行零件建模过程中往往避免不了修改&#xff0c;但在修改后又常常会出现零件报错的情况&#xff0c;设计树中会出现一堆的错误和警告&#xff0c;我们如何快速处理这些问题呢&#xff1f; 我们都知道SOLIDWOKRS零件通常包含两大类的对象&#xff0c;分别…

骑行无界,勇者无限!2024COSP上海国际户外展带您畅享生活的速度与激情!

随着夏日来临&#xff0c;越来越多的人选择借由“绿色骑行”去触碰一座城市的脉搏&#xff0c;“城市骑行”正在成为时尚潮流活动和生活休闲方式。对于一部分城市打工人来说&#xff0c;自行车是一种通勤的工具&#xff0c;骑行成为健身的新选择。 在小红书里输入“骑行”&…

Python语言在地球科学交叉领域中的技术应用

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;Python能够运行在Linux、Windows、Macintosh、AIX操作系统上及不同平台&#xff08;x86和arm&#xff09;&#xff0c;Python简洁的语法和对动态输入的支持&#xff0c;再加上解释性语言的本质&…

以30大龄转行AI真的难吗?绝对不是的!

前言 在这个快速变化的时代&#xff0c;"30岁门槛"似乎成了许多人心中的一道坎&#xff0c;尤其是在考虑职业转型时。当提到转向人工智能&#xff08;AI&#xff09;这样技术驱动的领域&#xff0c;一些人可能会担忧年龄成为阻碍。然而&#xff0c;事实证明&#xf…

深度学习Week15——利用TensorFlow实现猫狗识别2

文章目录 深度学习Week15——利用TensorFlow实现猫狗识别2—数据增强 一、前言 二、我的环境 三、前期工作 1、配置环境 2、导入数据 四、数据预处理 1、加载数据 2、可视化数据 3、检查数据 4、配置数据集 五、构建VGG-16模型 1、设置动态学习率 2、早停与保存最佳模型参数 五…

华为OD机试 - 图像物体的边界 - 深度优先搜索(Java 2024 D卷 200分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测…

栈的最小值

题目链接 栈的最小值 题目描述 注意点 执行push、pop和min操作的时间复杂度必须为O(1) 解答思路 使用两个栈&#xff0c;一个栈deque存储栈中对应的元素值&#xff0c;另一个栈minDeque存储当前栈中所有元素的最小值&#xff0c;当执行push(int x)操作&#xff0c;deque直…

2041:【例5.9】新矩阵

#include <iostream> using namespace std; int main(){const int N 21;//几行几列 int g[N][N] {};int n 0;cin >> n;for (int i 1; i < n; i){for (int j 1; j < n; j){// 输入到几行几列 cin >> g[i][j];if (i j || i j n 1){//如果是这种…

【计算机毕设】基于SpringBoot的民宿在线预定平台设计与实现 - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 本研究旨在设计并实现一个基于SpringBoot的民宿在线预定平台。通过信息化手段提高民宿预定效率&#xff0c;方便用户查询房源、预定房间、在线支付和…

嵌入式Linux系统编程 — 1.2 文件管理与错误处理

目录 1 Linux 系统如何管理文件 1.1 什么是静态文件 1.2 扇区&#xff08;Sector&#xff09;和块&#xff08;Block&#xff09;概念&#xff1f; 1.3 inode 1.4 进程控制块&#xff08;PCB&#xff09; 2 返回错误处理与 errno 2.1 errno变量介绍 2.3 perror函数介绍…

SwiftUI 利用 Swizz 黑魔法为系统创建的默认对象插入新协议方法(三)

功能需求 在 SwiftUI 的开发中,我们往往需要借助底层 UIKit 的“上帝之手”来进一步实现额外的定制功能。比如,在可拖放(Dragable)SwiftUI 的实现中,会缺失拖放取消的回调方法让我们这些秃头码农们“欲哭无泪” 如上图所示,我们在拖放取消时将界面中的一切改变都恢复如初…

年中企业业绩管理新篇章:用友BIP收入云助力高效管理!

随着市场竞争的加剧&#xff0c;年中时刻对于企业而言&#xff0c;不仅是评估上半年业绩的节点&#xff0c;更是调整策略、确保全年目标达成的关键时期。高效的业绩管理不仅需要明确的目标设定和计划制定&#xff0c;更需要借助先进的信息技术工具来提升管理效率和决策质量。在…

Java项目:98 springboot在线教育系统

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本系统共有管理员、用户等角色 本在线教育系统管理员功能有个人中心&#xff0c;用户管理&#xff0c;讲师管理&#xff0c;普通管理员管理&#xff…