首页 > 编程语言 >快速入门C++正则表达式

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

时间:2024-06-04 16:59:46浏览次数:22  
标签:std 字符 abc 匹配 入门 正则表达式 C++ regex 表达式

正则表达式(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
    通过该网站可以测试正则表达式的效果,并直观地看到匹配项:
    在这里插入图片描述

标签:std,字符,abc,匹配,入门,正则表达式,C++,regex,表达式
From: https://blog.csdn.net/LeoLei8060/article/details/139447853

相关文章

  • Python教程-快速入门基础必看课程09-文件处理
    该视频主要讲述了Python中文件的读写操作和pandas库中的subt函数来处理CSV文件。在Python中,文件的读写操作需要使用open函数打开文件,并指定路径和模式。读取文件时,可以使用f.read()方法读取内容,并使用f.close()方法关闭文件。写入文件时,可以使用f.write()方法写入内容,并使用......
  • C++知识点
    explicit关键字explicit关键字explicit关键字在理解explicit关键字之前,我们必须要了解构造函数的类型转换作用,以便于我们更好的理解explicit关键字,如果有不懂构造函数,可以来看看这篇文章:构造函数点击查看代码classDate{public://构造函数Date(intyear):_......
  • 华为OD机试2024年最新题库(Python、JAVA、C、C++合集)C卷+D卷
    介绍博主介绍:CSDN领军人物top1的作者,全网粉丝30w+,文章累计被阅读3800w+,直接帮助200+,间接帮助800+同学进入od添加或私信博主免费获取本题解析以及代码24年5月份开始,考的都是OD统一考试(D卷),题库已经整理好了,命中率95%以上。5-10月份考的都是D卷真题,都是原题,圈内有多种......
  • C++ 强制类型转换运算符简介
    C++提供了四种强制类型转换运算符:static_cast、reinterpret_cast、const_cast和dynamic_cast。这些运算符各自具有特定的用途,适用于不同的类型转换需求。本文将详细介绍这四种运算符及其应用场景,并讨论它们在向上转换中的使用方法。1.static_caststatic_cast用于在编译时执......
  • C++ Builder 2010 绘制坐标
     一、步骤:1.先确定Image的位置,大小(可以不写)          2.设置初始面板,绘制初始的x,y坐标轴          3.画x,y向的刻度线,标刻x,y轴刻度          4.获取数据(可以不写)          5.将数......
  • Dynamics CRM 365 Web API 入门
    创建VisualStudio项目启动VisualStudio2022,然后选择“创建新项目”。创建新的控制台应用项目。通过设置“位置”和“项目名称”来配置项目。通过选择“.NET8.0(长期支持)”和“不使用顶级语句”来配置项目。然后单击“创建”。编辑Program.cs按照以下后续步骤为主程......
  • AI绘画最新Stable Diffusion安装包+教程+模型+插件+全套入门资料来了,免费拿!
    大家好,我是设计师阿威这篇文章主要给大家分享一些AI绘画方面的学习资料、AI工具以及模型插件、视频教程等等。如果你是新手入门,就一定不要错过这些资料!获取方式:请查看文章底部1.stablediffusion安装包随着技术的迭代,目前StableDiffusion已经能够生成非常艺术化的......
  • 如何选择实名认证接口?C++身份证二、三要素实名认证接口提供厂商
    线上平台进行身份证实名认证,有助于保障交易的安全性,防止身份信息被盗用的风险,其主要应用于金融、在线银行、支付平台、社交媒体、账号注册、内容发布等多种应用场景。那么,又当如何选择实名认证接口厂家呢?翔云人工智能开放平台专注于API接口的提供,为有需要的企业提供了便......
  • C++发票查验真假的接口厂家有哪些?数电票、医疗票据查验
    现如今,随着数字化应用的不断普及,财务工作也在不断的由人工向数字化转型。企业财务进行数字化转型,能够推动财务管理职能的转型升级,通过运用云计算、大数据等技术,重构财务组合和业务流程,实现业财融合,提升会计信息质量、工作效率、合规程度及价值创造能力。翔云人工智能开放......
  • C++发票查验真假的接口厂家有哪些?数电票、医疗票据查验
    现如今,随着数字化应用的不断普及,财务工作也在不断的由人工向数字化转型。企业财务进行数字化转型,能够推动财务管理职能的转型升级,通过运用云计算、大数据等技术,重构财务组合和业务流程,实现业财融合,提升会计信息质量、工作效率、合规程度及价值创造能力。翔云人工智能开放平......