【C++技能树】快速文本匹配 --正则表达式介绍与C++正则表达式使用

在这里插入图片描述
Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法…感兴趣就关注我吧!你定不会失望。
在这里插入图片描述

0.正则表达式存在必要性

在日常生活,或者刷题过程中我们难免需要检测一段字符是否需要是否符合规定,或在一大段字符中寻找自己想要的信息.

**一个字一个字来看**十分的费劲且效率低下.有没有一种方法可以快速的匹配到自己需要的文本呢?

假设要判断一个QQ号是否有效,他必须满足以下三个规则

  • 长度大于等于5,且小于等于11
  • 首位不能是0
  • 是否为纯数字

这项工作可以通过c语言来完成

string qq;
cin>>qq;
bool valid=true;
if(qq.legth()<5||qq.length()>11)
    valid=false;
if(qq[0]=='0')
    valid=false;
for(int i=0;i<qq.length();i++)
{
    if(qq[i]<'0'||qq[i]>'9')
        valid=false;
}
if(valid)
    cout<<"valid"<<endl;
else
    cout<<"invalid"<<endl;

虽然看起来很简单就能判断出来了.但这仅是含有数字的QQ号,若我需要判断E-Mail、地址…相信那时的工作绝不是这几行代码就能结束的.

如果使用正则表达式来完成这项工作.代码就会进一步的简介(关于正则表达式的具体语法我们暂且按下不表)

string qq;
cin>>qq;
regex qq_match("[^0][0-9]{4,10}");
bool ret=regex_match(qq,qq_match);
cout<<(ret==true:"valid"?"invalid")<<endl;

仅需五行代码就可以达到上面同等的效果,下面来一起进入正则表达式的世界吧

1.正则表达式介绍

概念就不细说了,仅需要知道:

其叫正则表达式,也叫规则表达式,regex.其核心就是使用特定的文本作为规则,然后去匹配一般的字符串中符合符合这个规则的部分.正则表达式的泛用性很强,在很多高级语言中都有出现.其匹配规则是不变的,改变的仅是使用的函数,

正则表达式的优点很多

  1. 灵活且逻辑性强
  2. 可以迅速的以简单的方式达到字符串的控制

缺点就是难,但这应该是我的问题(doge

2.元字符及匹配规则的介绍

^:匹配行的开头:

通常目的是要求正则表达式精确的匹配开头的部分

$:匹配行的结尾:

通常目的是为了精确的匹配到结尾的位置

.:可以匹配除/r与/n以外的任何字符:

r.t 可以匹配到rat也可以匹配到rut

[…]:可以匹配到[]内的任意一个字符

[abcdef]可以匹配到apple

而[ ^abcdef] 则表示可以匹配不在[]范围内的任何字符,plain

[a-z]是范围匹配,可以匹配到小写字母a-z的任意一个

所以[ ^a-z]则表示非小写字母中的任何一个

(…):设定分组

\:转义字符:

所有语言都有的转义字符.也就是\n可能在这个语言中代表的是换行,但是你若就是想匹配其原来的意思,你就可以加上\

此时表示的是匹配\n

\d匹配数字0-9:

相当于[0-9]

\D取反\d:

相当于[ ^0-9]

\w匹配字母数字下划线:

相当于[a-zA-Z0-9_]

\W取反\w:

相当于[ ^a-zA-Z0-9_]

+前面的元素重复一次或多次:

例如zo+可以匹配到"zo" "zooo"但不能匹配到z因为其一次都没出现过

*****前面的任意元素出现了任意次:

例如zo*可以匹配到"zo" “zooo” “z

**?**前面的元素出现了一次或零次:

例如:thu(er)?可以匹配到thuer,也可以匹配到thu,但不能匹配到thuerer,因为出现了两次

{n}前面的元素出现了n次:

例如"o{2}“可以匹配到"foot” 也可以匹配到"boot,但不能匹配到"Bob"(因为只出现了一次)

{n,}前面的元素出现至少n次:

例如,o{2,}可以匹配到"foooood"但不能匹配到"bob"(因为只出现了一次)

**{n,m}**前面的元素至少出现了n次,最多出现了m次:

例如"o{1,3}"将匹配的"foooooood"前六个o为两组,最后一个o为一组

"o{0,1}等价于(o)?"注意{0,1}之间不能有空格

|逻辑或:

[z|f]ood可以匹配到"food"或者"zood".

以上为较为常见的正则表达式元字符,灵活使用已经可以解决大部分情况

3.C++正则表达式函数:

其包含头文件为

#include<regex>

Regex_match:

常用的匹配函数为其存在标准命名空间里,这里填入需要匹配的表达式

std::regex_match(匹配对象,匹配方式)

例如现在需要匹配一个以下格式的字符串:tel:086-0666-88810009999,利用上面所学知识可以轻松的写出来的他的正则表达式

1{1,3}-[0] [0-9]{2,3}-[0,9]{8,11}$,来解释一下他的含义.

首先从行开头开始:^,前1-3个数字为0-9:[0,9]{1,3},然后出现数字0一位数字0-9二到三个:[0] [0,9]{2,3}

之后再出现八到十一个数字:[0,9]{8,11} 之后就是行结尾:$>

下面是其c++代码示例

#include<iostream>
using namesapce std;
int main()
{
    string tel;
    cin>>tel;
    regex tel_reg("^tel:[0-9]{1,3}-[0][0-9]{2,3}-[0-9]{8,11}$");
    bool ret=regex_match(tel,tel_reg);
    cout<<(ret?"Valid":"Invalid")<<endl;
}

Regex_repelace

regex_place(匹配对象,匹配方式,替换内容)

下面这段内容为将"he…ll…o, wor…l…d! “中的.全部删掉,也就是替换成”"

#include<iostream>
using namesapce std;
int main()
{
    std::string str = "he......ll..o, wor...l...d!";
    regex reg("\\.");
    cout<<regex_replace(str,reg,"");
}

下面为一些常见的正则表达式匹配文本(可用作理解正则表达式):

  1. 验证用户名和密码:"2\w{5,15}$“正确格式:”[A-Z][a-z]_[0-9]"组成,并且第一个字必须为字母,长度6~16位;

  2. 验证电话号码:"^(\d{3,4}-)\d{7,8}$"正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx;

  3. 验证手机号码(包含虚拟号码和新号码段):“^1([38][0-9]|4[5-9]|5[0-3,5-9]|66|7[0-8]|9[89])[0-9]{8}$”;

  4. 验证身份证号(15位):“\d{14}[[0-9],0-9xX]”,(18位):“\d{17}(\d|X|x)”;

  5. 验证Email地址:“^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$“或者”[a-zA-z0-9_]+@[a-zA-z0-9]+(.[a-zA-z]+){1,3}”;

  6. 只能输入由数字和26个英文字母组成的字符串:“3+$”;

  7. 整数或者小数:“4+([.][0-9]+){0,1}$”;

  8. 只能输入数字:“5*$”;

  9. 只能输入n位的数字:“^\d{n}$”;

  10. 只能输入至少n位的数字:“^\d{n,}$”;

  11. 只能输入m~n位的数字:“^\d{m,n}$”;

  12. 只能输入零和非零开头的数字:“^(0|[1-9][0-9]*)$”;

  13. 只能输入有两位小数的正实数:“6+(.[0-9]{2})?$”;

  14. 只能输入有1~3位小数的正实数:“7+(.[0-9]{1,3})?$”;

  15. 只能输入非零的正整数:“^+?[1-9][0-9]*$”;

  16. 只能输入非零的负整数:“^-[1-9][0-9]*$”;

  17. 只能输入长度为3的字符:“^.{3}$”;

  18. 只能输入由26个英文字母组成的字符串:“8+$”;

  19. 只能输入由26个大写英文字母组成的字符串:“9+$”;

  20. 只能输入由26个小写英文字母组成的字符串:“10+$”;

  21. 验证是否含有^%&',;=? 等 ¨ 字符: " [ \"等字符:"[%&',;=? ¨字符:"[^“]+”;

  22. 只能输入汉字:“11{0,}$”(这里使用了Unicode字符码哦);

  23. 验证URL:“^https?😕/([\w-]+.)+[\w-]+(/[\w-./?%&=]*)?$”;

  24. 验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:“01"~"09"和"10"~"12”;

  25. 验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;“01"~"09”、"10"~"29"和“30”~“31”;

  26. 获取日期正则表达式:“^\d{4}[年|-|.]\d{\1-\12}[月|-|.]\d{\1-\31}日?$”(可用来匹配大多数年月日信息);

  27. 匹配双字节字符(包括汉字在内):“[^\x00-\xff]”(可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1));

  28. 匹配空白位置"[\f\n\r\t\v]"(可以用来删除空白行);

  29. 匹配HTML标记的正则表达式:“<(\S?)[^>]>.?</>|<.? />”(这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力);

  30. 匹配首尾空白字符的正则表达式:"^\s|\s$"(可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式);**

  31. 匹配网址URL的正则表达式:“[a-zA-z]+://[^\s]*”;

  32. 匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):“12[a-zA-Z0-9_]{4,15}$”;

  33. 匹配腾讯QQ号:“[1-9][0-9]{4,10}”;

  34. 匹配中国邮政编码:“[1-9]\d{5}(?!\d)”(中国邮政编码为6位数字);

  35. 匹配ip地址:“([1-9]{1,3}.){3}[1-9]”(提取ip地址时有用);

  36. 匹配MAC地址:(“[A-Fa-f0-9]{2}😃{5}[A-Fa-f0-9]”。


  1. 0-9 ↩︎

  2. a-zA-Z ↩︎

  3. A-Za-z0-9 ↩︎

  4. 0-9 ↩︎

  5. 0-9 ↩︎

  6. 0-9 ↩︎

  7. 0-9 ↩︎

  8. A-Za-z ↩︎

  9. A-Z ↩︎

  10. a-z ↩︎

  11. \u4e00-\u9fa5 ↩︎

  12. a-zA-Z ↩︎

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ppeua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值