本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:C++11 – 快速学会正则表达式
原文链接:https://www.stubbornhuang.com/1840/
发布于:2021年11月22日 10:31:40
修改于:2021年11月22日 10:31:40
转载自:https://ayaka.shn.hk/cppregex/
1 概述
C++ 中正则表达式通常使用 R"(...)" 的形式,相当于 Python 中的 r"...",保证字符串内部的 \ 等字符不被转义。但是,R"(...)" 中的 () 是语法的一部分,一定不要当成字符串里面的内容。例如,R"(1234)" 表示字符串 "1234",而不是 "(1234)"。
创建正则表达式使用如下形式:
const std::regex re { R"(\S+)" };
如果要指定忽略大小写, 则使用如下形式:
const std::regex re { R"(\S+)", std::regex::icase };
2 查找
2.1 判断是否完全匹配
使用 std::regex_match 函数,第一个参数为字符串,第二个参数为正则表达式,返回值为 bool。
2.1.1 示例:验证电话号码
假设电话号码为 xxx-xxxxx 的形式
#include <iostream>
#include <regex>
int main() {
const std::regex re { R"(\d{3}-\d{5})" };
const std::string str1 = "123-12345";
const bool matched1 = std::regex_match(str1, re);
std::cout << (matched1 ? "Yes" : "No") << std::endl;
const std::string str2 = "123-12345a";
const bool matched2 = std::regex_match(str2, re);
std::cout << (matched2 ? "Yes" : "No") << std::endl;
}
输出:
Yes
No
2.1.2 密码格式验证
在设置密码时,要求至少包含一个小写字母、一个大写字母、至少一个标点字符,并且至少有 6 个字符长。
同上例,第一个参数为待验证的密码字符串,第二个参数为正则表达式:
(?=.*[a-z])(?=.*[A-Z])(?=.*[[:punct:]]).{6,}
2.2 判断是否局部匹配
使用 std::regex_search 函数,第一个参数为字符串,第二个参数为正则表达式,返回值为 bool。
它与 std::regex_match 的区别是,std::regex_search 只要局部匹配就返回 true,而 std::regex_match 必须完全匹配整个字符串。
2.2.1 示例:判断每行是否均在 20 字符以内
#include <iostream>
#include <regex>
int main() {
const std::regex re { R"(^.{21,}$)" };
const std::string str =
R"(0123456789012345
012345678901234567
0123456789012345678901
0123456)";
const bool matched = std::regex_search(str, re);
std::cout << (!matched ? "Yes" : "No") << std::endl;
}
输出:
No
2.3 统计匹配个数
使用std::distance函数
2.3.1 示例:统计词数
#include <iostream>
#include <regex>
#include <iterator>
int main() {
const std::regex re { R"(\S+)" };
const std::string str = "Lorem ipsum dolor sit amet, consectetur";
const std::sregex_iterator begin { str.cbegin(), str.cend(), re }, end;
const auto count = std::distance(begin, end);
std::cout << count << std::endl;
}
输出:
6
3 提取
3.1 完全匹配并提取分组
使用 std::regex_match 函数,第一个参数为字符串,第二个参数为匹配结果,第三个参数为正则表达式。返回值为 bool,若匹配成功,则返回 true,且匹配结果存入第二个参数中。
3.1.1 示例:匹配字母加数字
#include <iostream>
#include <regex>
int main() {
const std::regex re { R"(([A-Za-z]+)([0-9]+))" };
const std::string str = "ABC9876543";
std::smatch match;
if (std::regex_match(str, match, re)) {
const std::ssub_match match_1 = match[1];
const std::ssub_match match_2 = match[2];
std::cout << match_1.str() << ' ' << match_2.str() << std::endl;
}
}
输出:
ABC 9876543
3.2 局部匹配并提取分组
使用 std::regex_search 函数,第一个参数为字符串,第二个参数为匹配结果,第三个参数为正则表达式。返回值为 bool,若匹配成功,则返回 true,且匹配结果存入第二个参数中。
它与 std::regex_match 的区别是,std::regex_search 只要局部匹配就返回 true,而 std::regex_match 必须完全匹配整个字符串。
3.2.1 示例:匹配长度为 5 的单词的前两个字母
#include <iostream>
#include <regex>
int main() {
const std::regex re { R"(\b([a-z]{2})[a-z]{3}\b)" };
const std::string str = "thread look welcome high merit cup";
std::smatch match;
if (std::regex_search(str, match, re)) {
const std::ssub_match match_1 = match[1];
std::cout << match_1.str() << std::endl;
}
}
输出:
me
3.3 获取所有匹配
使用 std::sregex_iterator,然后对迭代器使用 it->str()。
3.3.1 示例:逐行输出所有单词
import <iostream>
import <regex>
int main() {
const std::regex re { R"(\S+)" };
const std::string str = "Lorem ipsum dolor sit amet, consectetur";
for (std::sregex_iterator it { str.cbegin(), str.cend(), re }, end; it != end; ++it)
std::cout << it->str() << std::endl;
}
输出:
Lorem
ipsum
dolor
sit
amet,
consectetur
3.4 从所有匹配中提取分组
使用 std::sregex_iterator,然后对迭代器使用 (*it)[1]
3.4.1 示例:匹配十六进制数的数字部分
#include <iostream>
#include <regex>
int main() {
const std::regex re { R"(0x([0-9a-f]+))" };
const std::string str = " 0x1d782 0x86fa1 0x54b67 ";
for (std::sregex_iterator it { str.cbegin(), str.cend(), re }, end; it != end; ++it)
std::cout << (*it)[1] << std::endl;
}
输出
1d782
86fa1
54b67
4 分割
4.1 分割字符串
4.1.1 示例:根据空白字符分割单词(类似 Python 中 re.split)
#include <iostream>
#include <list>
#include <regex>
std::list<std::string> split(const std::string& str, const std::regex& delim) {
const std::sregex_token_iterator
begin { str.cbegin(), str.cend(), delim, -1 }, end;
return { begin, end };
}
int main() {
const std::string str = " Lorem ipsum \n dolor sit \t amet, consectetur ";
const std::regex delim { R"(\s+)" };
const auto tokens = split(str, delim);
for (const std::string& token : tokens)
std::cout << token << std::endl;
}
输出
Lorem
ipsum
dolor
sit
amet,
consectetur
5 替换
5.1 替换字符串
使用 std::regex_replace。
5.1.1 示例
#include <iostream>
#include <regex>
int main() {
const std::regex re { R"(<(\/?)h1>)" };
const std::string str = "<h1>Apples</h1><p>I like apples.</p>\n"
"<h1>Bananas</h1><p>I also like bananas.</p>";
const std::string res = std::regex_replace(str, re, "<$1h2>");
std::cout << res << std::endl;
}
当前分类随机文章推荐
- C++ – UTF8编码下的全角字符转半角字符 阅读1810次,点赞0次
- C++11 - std::chrono - 使用std::chrono::duration_cast进行时间转换,hours/minutes/seconds/milliseconds/microseconds相互转换,以及自定义duration进行转换 阅读2247次,点赞0次
- C++STL容器 - std::vector元素访问方式总结 阅读920次,点赞0次
- C++ - std::string替换字符串中所有指定的子字符串 阅读2843次,点赞1次
- C++ - 我在项目实际开发中用到的第三方库/开源项目,涵盖网络、加密解密、GUI、网络、音视频、图片等等 阅读248次,点赞0次
- C++11 - 使用std::thread::join()/std::thread::detach()方法需要注意的点 阅读2891次,点赞0次
- C++ - 使用std::chrono获取当前秒级/毫秒级/微秒级/纳秒级时间戳 阅读3540次,点赞0次
- C++ - Jni中的GetByteArrayElements和GetByteArrayRegion的区别和使用示例 阅读3099次,点赞0次
- C++STL容器 - std::vector构造方式与分配值方式总结 阅读834次,点赞0次
- C++ - 字节数组byte[]或者unsigned char[]与int的相互转换 阅读7102次,点赞1次
全站随机文章推荐
- C++ - queue存储动态指针时正确释放内存 阅读5539次,点赞2次
- Python - 各种包安装、导入问题总结 阅读2210次,点赞0次
- 姿态估计之Openpose-Body25数据集骨骼关节keypoint标注对应 阅读8401次,点赞5次
- 资源分享 - Artificial Intelligence - A Modern Approach , First Edition 英文高清PDF下载 阅读1472次,点赞0次
- 资源分享 - Real-Time Collision Detection 英文高清PDF下载 阅读2030次,点赞0次
- 资源分享 - An Introduction to Computational Fluid Dynamics - The Finite Volume Method (First Edition)英文高清PDF下载 阅读402次,点赞0次
- C++ 回调函数 阅读3036次,点赞0次
- Blender - 为模型贴透明贴图 阅读575次,点赞0次
- OpenCV - cv::VideoWriter::fourcc可支持的视频编码格式 阅读2888次,点赞0次
- 资源分享 - Jim Blinn's Corner - Notation, Notation, Notation 英文高清PDF下载 阅读1996次,点赞0次
评论
169