在 C++ 中,正则表达式(regex)是一种用于匹配字符串模式的强大工具。正则表达式不仅能帮助你查找符合特定模式的字符,还能捕获匹配的子字符串(即分组捕获)。这篇文章将介绍 C++ 正则表达式中的分组捕获机制,并提供多个示例代码来帮助你快速入门。
一、基本概念:正则表达式分组捕获
正则表达式分组捕获是一种能够将匹配的部分提取出来的技术。在 C++ 中,正则表达式分组捕获通常通过小括号 ()
来实现。每个分组会捕获匹配到的子字符串,并且可以在代码中通过相应的索引访问它们。
分组的基本语法
()
:用于定义捕获分组。你可以在正则表达式中使用多个分组,C++ 中从1
开始对分组编号。
示例:简单分组捕获
假设我们需要从一个日期字符串中提取年月日,可以使用正则表达式中的分组捕获来实现。
二、C++ 正则表达式库:<regex>
在 C++ 中使用正则表达式时,需要包含头文件 <regex>
。基本的正则表达式操作包括:
std::regex
:正则表达式对象。std::smatch
:保存匹配结果的对象。std::regex_search
:查找匹配。std::regex_match
:完全匹配整个字符串。std::regex_replace
:替换匹配的字符串。
三、示例代码:日期分组捕获
我们可以编写一个示例程序,从一个字符串中提取出日期的年、月和日。
示例 1:提取日期(YYYY-MM-DD
)
假设我们有一个日期字符串 2023-02-25
,并希望通过正则表达式捕获出年、月、日。
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string input = "2023-02-25";
// 正则表达式:捕获年、月和日
std::regex pattern(R"((\d{4})-(\d{2})-(\d{2}))");
std::smatch matches;
// 如果匹配成功
if (std::regex_match(input, matches, pattern)) {
// 输出捕获的各个分组
std::cout << "Year: " << matches[1] << std::endl;
std::cout << "Month: " << matches[2] << std::endl;
std::cout << "Day: " << matches[3] << std::endl;
} else {
std::cout << "No match found." << std::endl;
}
return 0;
}
代码解析:
-
正则表达式
R"((\d{4})-(\d{2})-(\d{2}))"
:
(\d{4})
捕获4位数字(即年份)。(\d{2})
捕获2位数字(即月份和日期)。
-
matches[1]
、matches[2]
、matches[3]
分别存储匹配到的年份、月份和日期。
输出:
Year: 2023
Month: 02
Day: 25
四、捕获多个匹配
有时我们需要从文本中查找多个匹配项。std::regex_search
可以用于查找匹配,但它只会找到第一个匹配项。如果你想捕获所有匹配项,可以使用 std::regex_iterator
。
示例 2:提取所有匹配的日期
假设我们有一段文本,其中包含多个日期,我们希望提取所有日期。
#include <iostream>
#include <regex>
#include <string>
#include <iterator>
int main() {
std::string input = "The event will be held on 2023-02-25, followed by another on 2024-03-01.";
// 正则表达式:捕获日期
std::regex pattern(R"((\d{4})-(\d{2})-(\d{2}))");
std::smatch matches;
// 使用 regex_iterator 查找所有匹配
auto begin = std::sregex_iterator(input.begin(), input.end(), pattern);
auto end = std::sregex_iterator();
for (auto it = begin; it != end; ++it) {
std::cout << "Found date: " << it->str() << std::endl;
}
return 0;
}
输出:
Found date: 2023-02-25
Found date: 2024-03-01
使用 std::regex_search
来查找日期的所有匹配
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string input = "The event will be held on 2023-02-25, followed by another on 2024-03-01.";
// 正则表达式:捕获日期
std::regex pattern(R"((\d{4})-(\d{2})-(\d{2}))");
std::smatch matches;
// 使用 cbegin 和 cend 来获取常量迭代器
auto begin = input.cbegin();
while (std::regex_search(begin, input.cend(), matches, pattern)) {
// 输出匹配到的日期
std::cout << "Found date: " << matches[0] << std::endl;
// 更新搜索起始位置,继续从上一个匹配位置之后开始搜索
begin = matches[0].second;
}
return 0;
}
输出:
Found date: 2023-02-25
Found date: 2024-03-01
五、捕获和替换(regex_replace
)
正则表达式不仅可以用于查找和捕获,还可以用于替换匹配的内容。通过 std::regex_replace
,你可以将捕获到的内容替换成新的内容。
示例 3:替换日期格式
假设我们希望将日期格式从 YYYY-MM-DD
更改为 DD/MM/YYYY
。
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string input = "The event will be held on 2023-02-25, and another on 2024-03-01.";
// 正则表达式:捕获日期
std::regex pattern(R"((\d{4})-(\d{2})-(\d{2}))");
// 使用 regex_replace 将日期格式替换为 DD/MM/YYYY
std::string output = std::regex_replace(input, pattern, R"($3/$2/$1)");
std::cout << "Updated text: " << output << std::endl;
return 0;
}
输出:
Updated text: The event will be held on 25/02/2023, and another on 01/03/2024.
六、进阶应用:捕获多个分组
当正则表达式中有多个分组时,你可以通过 matches[n]
访问每个分组的捕获结果。
示例 4:捕获多个分组(例如,提取姓名和年龄)
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string input = "John Doe, Age: 30; Jane Smith, Age: 25";
// 正则表达式:捕获姓名和年龄
std::regex pattern(R"((\w+ \w+), Age: (\d+))");
std::smatch matches;
// 查找匹配
auto begin = std::sregex_iterator(input.begin(), input.end(), pattern);
auto end = std::sregex_iterator();
for (auto it = begin; it != end; ++it) {
std::cout << "Name: " << it->str(1) << ", Age: " << it->str(2) << std::endl;
}
return 0;
}
输出:
Name: John Doe, Age: 30
Name: Jane Smith, Age: 25
七、总结
正则表达式的分组捕获是一个非常强大的工具,它能够让你轻松提取和操作字符串中的特定部分。C++ 中的 <regex>
库提供了灵活的接口,允许你使用正则表达式进行模式匹配、捕获分组、查找多个匹配项以及进行替换操作。通过本文的示例代码,希望你能掌握 C++ 中正则表达式分组捕获的基础应用,并能在实际项目中灵活使用正则表达式来处理文本数据。