• 感谢大家访问本站,希望本站的内容可以帮助到大家!

  • 本站由于前段时间遭受到大量临时和国外邮箱注册,所以对可注册的邮箱类型进行了限制!

  • 本站会放置Google广告用于维持域名以及网站服务器费用。

  • 如果觉得本站的内容有帮助,可以考虑打赏博主哦!

  • 在本站开通年度VIP,无限制下载本站资源和阅读本站文章

  • 工资「喂饱肚子」,副业「养活灵魂」!

  • 欢迎大家交换友链,可在https://www.stubbornhuang.com/申请友情链接进行友链交换申请!

  • 计算机图形学与计算几何经典必备书单整理,下载链接可参考:https://www.stubbornhuang.com/1256/

  • 问题反馈可发送邮件到stubbornhuang@qq.com

C++11 – 快速学会正则表达式

C++ 发布于2021-11-22 阅读 3,989次 0次评论 2次点赞 本文共3956个字,阅读需要10分钟。

转载自: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;
}

欢迎扫码关注我的微信公众号,及时获取文章更新

微信公众号二维码

本文作者:StubbornHuang

版权声明:本文为站长原创文章,如果转载请注明原文链接!

原文标题:C++11 – 快速学会正则表达式

原文链接:https://www.stubbornhuang.com/1840/

发布于:2021年11月22日 10:31:40

修改于:2023年06月26日 21:01:44

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

文章末尾
上一篇
Duilib - RichEdit控件发送textchanged消息
Duilib
下一篇
资源分享 - Mathematics for Computer Graphics , Fifth Edition 英文PDF下载
计算几何与计算机图形学资源
当前分类随机文章推荐

发表评论

您必须 [ 登录 ] 才能发表留言!

关注我们的公众号

微信公众号