[项目前置]C++正则表达式

正则表达式介绍

正则表达式(Regular Expression,简称Regex)是一种强大的文本处理工具,它允许你以灵活和高效的方式搜索、替换、检验文本。在C++中,正则表达式的支持是通过标准库中的<regex>头文件提供的,该库自C++11起成为标准的一部分。

正则表达式使用一系列符号和字符来描述或匹配文本模式。这些模式可以简单到单个字符,也可以复杂到描述复杂的字符串模式。

C++标准库提供了多种与正则表达式相关的类和函数,位于<regex>头文件中,包括:

  • std::regex:编译后的正则表达式对象。
  • std::regex_match:检查给定的字符串是否完全匹配正则表达式。
  • std::regex_search:在给定的字符串中搜索正则表达式的匹配。
  • std::regex_replace:使用正则表达式匹配模式来替换字符串。

常用符号和术语

  • 字面量:匹配特定字符的自身。
  • .(点):匹配任何单个字符,除了换行符。
  • []:字符集,匹配方括号内的任意字符。
  • ^ :行的开始,[^]中的^表示非。
  • $:行的结束。
  • *:前面的元素零次或多次出现。
  • +:前面的元素一次或多次出现。
  • ?:前面的元素零次或一次出现。
  • {n}:前面的元素恰好出现n次。
  • {n,}:前面的元素至少出现n次。
  • {n,m}:前面的元素至少出现n次,但不超过m次。
  • |:或,匹配左边或右边的表达式。
  • () :分组,将几个项当作一个单元进行处理,通常与|结合使用。

正则表达式的使用其实很简单,只需要为字符串创造一个匹配规则对象regex,并设置合适的规则。

举例1

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

int main() {
    std::string text = "Hello World 123";
    std::regex pattern("World");

    // 检查模式是否匹配
    if (std::regex_search(text, pattern)) {
        std::cout << "Found a match!" << std::endl;
    } else {
        std::cout << "No match found." << std::endl;
    }

    return 0;
}

这个示例将输出"Found a match!",因为字符串"Hello World 123"中确实包含"World"。

举例2

验证电子邮箱地址

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

int main() {
    std::string email = "example@example.com";
    std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");

    if (std::regex_match(email, pattern)) {
        std::cout << "The email address is valid." << std::endl;
    } else {
        std::cout << "The email address is not valid." << std::endl;
    }

    return 0;
}

在C++中,R"(...)"是一种原始字符串字面量(Raw String Literal)的表示方法,它允许你包含任何字符序列作为字符串的一部分,包括反斜杠 \、双引号 " 和换行符等,而不需要进行转义。

这个规则对于正则表达式的特殊字符(如*, +, ?, |, (, ), [, ], {, }, ^, $, 和.等)不适用,因为这些特殊字符在正则表达式中有特定的含义,

  1. [a-zA-Z0-9._%+-]+:这部分是电子邮件地址的用户名部分,表示电子邮箱可以包含:

    • 小写字母 (a-z)
    • 大写字母 (A-Z)
    • 数字 (0-9)
    • 下划线 (_)
    • 点 (.)
    • 百分号 (%)
    • 加号 (+)
    • 减号 (-)

    + 表示前面的字符集 [a-zA-Z0-9._%+-] 可以出现一次或多次。

  2. @:这是电子邮件地址中必须出现的"@"字符,用于分隔用户名和域名部分。

  3. [a-zA-Z0-9.-]+:这是域名部分,表示电子邮箱可以包含:

    • 小写字母 (a-z)
    • 大写字母 (A-Z)
    • 数字 (0-9)
    • 点 (.)
    • 减号 (-)

    与用户名部分类似,+ 表示这个字符集可以出现一次或多次。

  4. \. :表示点字符(.)。在正则表达式中,点(.)通常表示任何单一字符,因此需要用反斜线(\)进行转义,使其表示字面上的点字符。这个点在电子邮件地址中用于分隔域名和顶级域名(TLD)。

  5. [a-zA-Z]{2,} :这是顶级域名(TLD)部分,可以包含小写字母 (a-z) 和大写字母 (A-Z)。{2,} 表示这部分至少有两个字符,没有上限。这反映了顶级域名通常至少有两个字母,如 .com.org.net 等。

举例3

替换文本

使用正则表达式替换文本中的特定单词或字符。这个例子将文本中的所有"is"替换为"is not"。

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

int main() {
    std::string text = "This is a test. This test is simple.";
    std::string replaceWith = "is not";
    std::regex pattern(R"(\bis\b)");

    std::string result = std::regex_replace(text, pattern, replaceWith);

    std::cout << result << std::endl;

    return 0;
}
  1. \b :这是一个正则表达式的边界匹配符,它用于匹配一个词的边界。词的边界是指不被字母、数字或下划线(\w)字符包围的位置。这包括字符串的开头和结尾,以及空格或标点符号和字母数字之间的位置。使用\b可以确保你匹配的是独立的单词,而不是包含在其他单词中的子字符串。

  2. is:这部分表示要直接匹配的字符串"is"。

  3. \b:再次使用,确保"is"后面也是一个单词边界。

因此,整个表达式R"(\bis\b)"用于匹配作为独立单词存在的"is",而不会匹配像"this"或"island"这样包含"is"作为子字符串的单词。

举例4

验证字符串是否符合特定的电话号码格式。这里考虑的格式是匹配符合特定格式的中国大陆电话号码。例如+86-123-4567-8910

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

int main() {
    std::string phone = "+1-123-456-7890";
    std::regex pattern(R"(\+86-\d{3}-\d{4}-\d{4})");

    if (std::regex_match(phone, pattern)) {
        std::cout << "The phone number is valid." << std::endl;
    } else {
        std::cout << "The phone number is not valid." << std::endl;
    }

    return 0;
}
  1. \+ :这里的加号(+)是一个特殊字符,在正则表达式中用于表示前面的元素可以出现一次或多次。但当你想要匹配字面上的加号字符时,需要使用反斜杠对其进行转义,所以\+表示匹配字面上的"+"字符。

  2. 86:这部分直接匹配数字"86",代表中国大陆的国家代码。

  3. -:匹配字面上的连字符或破折号。

  4. \d{3}\d是一个特殊的字符类,匹配任意数字(0-9)。大括号{3}指定了前面的\d(数字)必须恰好出现3次。因此,\d{3}匹配一个由3个数字组成的序列。

  5. -:再次匹配字面上的连字符。

  6. \d{4} :这里\d{4}意味着必须有一个由4个数字组成的序列。和前面一样,\d表示数字,{4}指定了数字必须恰好出现4次。

  7. -:匹配字面上的连字符。

  8. \d{4} :和前面的\d{4}一样,这也是一个由4个数字组成的序列。

举例5

解析http响应

HTTP响应由状态行、响应头部、空行和响应体组成。我们的目标是从HTTP响应文本中提取状态码、响应头部以及响应体。

示例HTTP响应文本

css 复制代码
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 138

<html>
<head>
<title>An Example Page</title>
</head>
<body>
Hello World, this is a very simple HTML document.
</body>
</html>

我们将编写一个C++程序来解析上述HTTP响应,提取出状态码、Content-TypeContent-Length头部以及响应体。

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

int main() {
    // 示例HTTP响应文本
    std::string httpResponse = R"(HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 138

<html>
<head>
<title>An Example Page</title>
</head>
<body>
Hello World, this is a very simple HTML document.
</body>
</html>)";

    // 正则表达式匹配状态码、Content-Type、Content-Length和响应体
    std::regex statusLinePattern(R"(HTTP\/\d\.\d\s(\d{3}))");
    //(\d{3})括号表示要取出的内容
    // \s表示代表任何空白字符(空格、制表符、换行符....)
    std::regex contentTypePattern(R"(Content-Type:\s(.+))");
    std::regex contentLengthPattern(R"(Content-Length:\s(\d+))");
    std::regex bodyPattern(R"(\r\n\r\n([\s\S]*))"); 
    // [\s\S]* 匹配包括换行符在内的任意字符

    std::smatch matches;

    // 匹配状态码
    if (std::regex_search(httpResponse, matches, statusLinePattern)) {
        std::cout << "Status Code: " << matches[1] << std::endl;
    }

    // 匹配Content-Type
    if (std::regex_search(httpResponse, matches, contentTypePattern)) {
        std::cout << "Content-Type: " << matches[1] << std::endl;
    }

    // 匹配Content-Length
    if (std::regex_search(httpResponse, matches, contentLengthPattern)) {
        std::cout << "Content-Length: " << matches[1] << std::endl;
    }

    // 匹配响应体
    if (std::regex_search(httpResponse, matches, bodyPattern)) {
        std::cout << "Body:\n" << matches[1] << std::endl;
    }

    return 0;
}

std::smatch

在C++中,std::smatchstd::match_results模板类的一个特化版本,专门用于处理字符串(std::string)的搜索和匹配操作。当你使用正则表达式进行搜索或匹配时,std::smatch对象用于存储匹配结果。每个匹配结果包括完整的匹配以及任何括号内的子匹配(即捕获组)。

  • matches[0]包含了正则表达式完整匹配的文本。
  • matches[1]matches[2]、... 包含了正则表达式中第一个、第二个等括号内的子表达式(捕获组)匹配的文本。这些子匹配允许你访问正则表达式中由圆括号()定义的各个部分的匹配结果。
相关推荐
疯一样的码农18 小时前
Python 正则表达式(RegEx)
开发语言·python·正则表达式
小白学大数据21 小时前
正则表达式在Kotlin中的应用:提取图片链接
开发语言·python·selenium·正则表达式·kotlin
萧鼎2 天前
【Python】强大的正则表达式工具:re模块详解与应用
开发语言·python·正则表达式
柳叶寒3 天前
医院信息化与智能化系统(17)
java·nacos·gateway·全栈·项目
叮当喵是mao3 天前
接口测试(十)jmeter——关联(正则表达式提取器)
jmeter·正则表达式
Winston Wood4 天前
你需要了解的正则表达式相关知识
正则表达式
落霞的思绪4 天前
Javase——正则表达式
正则表达式
cyt涛5 天前
Docker — 跨平台和环境部署
java·运维·mysql·docker·容器·部署·项目
crownyouyou5 天前
python正则表达式
开发语言·python·正则表达式
柳叶寒6 天前
医院信息化与智能化系统(15)
java·数据库·全栈·项目