当前位置:   article > 正文

c++正则表达式的组成和使用

c++正则表达式

正则表达式的组成

正则是一种规则,它用来匹配(进而捕获、替换)原字符串。这种规则需要“模式”、“字符串”这两样东西,“模式”根据正则规则,来处理“字符串”。这种规则被许多语言支持,C++11以后才支持正则。

使用正则表达式需要包含 <regex> 库

  1. #include<regex>
  2. using namespace std;
  3. int main()
  4. {
  5. //构造正则对象
  6. regex regx("\\w");
  7. }

具有特殊意义的元字符

\:\字符能够改变字符原本的含义

^:^字符指示字符串的头,且要求字符串以字符开头,不占位。\^表示一个真正的^符号 (特殊字符具有特殊含义,如果字符串中有^,用\^表示字符本身)。

$:$字符指示字符串的尾,且要求字符串以字符结尾,不占位。\$表示一个真正的$符号。

():分组,大正则中包含小正则。可以改变默认的优先级。在模式中可以使用\1来表示第一组已然捕获到的东西(已匹配到的项)。

把一个字符串分成多组的形式用正则表达式去描述

yeeee@163.com.cn

yeeee   @   163   .com   .cn

第一部分是数字、字母、下划线即可,第二部分必须是要 @ ,第三部分是数字、字母、下划线,第四部分必须是.加上数字、字母、下划线

通过如上方式做字符的匹配

  1. int main()
  2. {
  3. //第一部分是字母数字下划线 第二部分也是字母数字下划线
  4. regex regx("(\\w)(\\1)");
  5. //等价于 (\\w)(\\b)(\\w)(\\b)
  6. regex regx("(\\w)(\\b)(\\1)(\\2)");
  7. //等价于 (\\w)(\\b)(\\w)
  8. regex regx("(\\w)(\\b)(\\1)");
  9. }

\b:指示字符串的边界(头/尾/空格左/空格右),字符\b要求边界的左边是字符,\b字符要求边界的右边是字符。

.:表示一个除了\n以外的任意一个字符。\.表示一个真正的.符号。

|:a | b a或b之一

[abc]:abc之中的任意一个

[^abc]:abc之外的

[a-z]:任意小写字母

[^a-z]:除了小写字母之外的

\w:任意一个字母数字下划线,等价于[(0-9)(a-z)(A-Z)(_)]

\W:字母数字下划线之外的任何一个字符,等价于[]

\d:任意一个数字

\D:除了数字之外的其他字符

\s:空白符(空格、制表符、换页符)

量词元字符

*:字符*要求字符出现0或更多次 {0,}

+:字符+要求字符出现1或更多次 (\w) {1,}

?:字符?要求字符出现0次或1次 {0,1}

{n}:字符{n}要求字符出现n次

{n,}:字符{n,}要求字符出现n或更多次 {0,}

{n,m}:字符{n,m}要求字符出现n到m次

所以含有\的元字符,在C++定义时,都要写成\\

校验数字的表达式

数字:^ [0 - 9] * $

n位的数字:^ \d{ n }$

至少n位的数字:^ \d{ n, }$

m - n位的数字: ^ \d{ m,n }$

零和非零开头的数字: ^ (0 | [1 - 9][0 - 9] *)$

非零开头的最多带两位小数的数字: ^ (\[1 - 9][0 - 9] *) + (.[0 - 9]{ 1,2 }) ? $

带1 - 2位小数的正数或负数: ^ (\ - ) ? \d + (\.\d{ 1,2 }) ? $

正数、负数、和小数: ^ (\ - | \ + ) ? \d + (\.\d + ) ? $

有两位小数的正实数: ^ [0 - 9] + (.[0 - 9]{ 2 }) ? $

有1~3位小数的正实数: ^ [0 - 9] + (.[0 - 9]{ 1,3 }) ? $

非零的正整数: ^ [1 - 9]\d * $ 或 ^ ([1 - 9][0 - 9] *) { 1, 3 }$ 或^ \ + ? \[1 - 9][0 - 9] * $

非零的负整数: ^ \ - [1 - 9][]0 - 9"$ 或 ^-[1-9]\d$

非负整数: ^ \d + $ 或 ^ [1 - 9]\d * | 0$

非正整数: ^ -[1 - 9]\d * | 0$ 或 ^ ((-\d + ) | (0 + ))$

非负浮点数: ^ \d + (.\d + ) ? $ 或 ^ [1 - 9]\d * .\d * | 0.\d * [1 - 9]\d * | 0 ? .0 + | 0$

非正浮点数: ^ ((-\d + (.\d + ) ? ) | (0 + (.0 + ) ? ))$ 或 ^ (-([1 - 9]\d * .\d * | 0.\d * [1 - 9]\d*)) | 0 ? \.0 + | 0$

正浮点数: ^ [1 - 9]\d * .\d * | 0.\d * [1 - 9]\d * $ 或 ^ (([0 - 9] + .[0 - 9] * [1 - 9][0 - 9] *) | ([0 - 9] * [1 - 9][0 - 9] * .[0 - 9] + ) | ([0 - 9] * [1 - 9][0 - 9] *))$

负浮点数: ^ -([1 - 9]\d * .\d * | 0.\d * [1 - 9]\d*)$ 或 ^ (-(([0 - 9] + .[0 - 9] * [1 - 9][0 - 9] *) | ([0 - 9] * [1 - 9][0 - 9] * .[0 - 9]) | ([0 - 9] * [1 - 9][0 - 9] *)))$

浮点数: ^ (-? \d + )(.\d + ) ? $ 或 ^ -? ([1 - 9]\d * .\d * | 0.\d * [1 - 9]\d * | 0 ? .0 + | 0)$

校验字符的表达式

汉字: ^ [\u4e00 - \u9fa5]{ 0, }$

英文和数字: ^ [A - Za - z0 - 9] + $ 或 ^ [A - Za - z0 - 9]{ 4,40 }$

长度为3 - 20的所有字符: ^ .{3, 20}$

由26个英文字母组成的字符串: ^ [A - Za - z] + $

由26个大写英文字母组成的字符串: ^ [A - Z] + $

由26个小写英文字母组成的字符串: ^ [a - z] + $

由数字和26个英文字母组成的字符串: ^ [A - Za - z0 - 9] + $

由数字、26个英文字母或者下划线组成的字符串: ^ \w + $ 或 ^ \w{ 3,20 }$

中文、英文、数字包括下划线: ^ [\u4E00 - \u9FA5A - Za - z0 - 9_] + $

中文、英文、数字但不包括下划线等符号: ^ [\u4E00 - \u9FA5A - Za - z0 - 9] + $ 或 ^ [\u4E00 - \u9FA5A - Za - z0 - 9]{ 2,20 }$

可以输入含有 ^ %&',;=?$"等字符:[^%&', ; = ? $\x22] + 12 禁止输入含有~的字符:[^ ~\x22] +

特殊需求表达式

Email地址: ^ \w + ([-+.]\w + ) * @\w + ([-.]\w + ) * .\w + ([-.]\w + ) * $

域名:[a - zA - Z0 - 9][-a - zA - Z0 - 9]{ 0,62 }(/ .[a - zA - Z0 - 9][-a - zA - Z0 - 9]{ 0,62 }) + / . ? InternetURL:[a - zA - z] + ://\s* 或 ^http://([\w-]+.)+[\w-]+(/[\w-./?%&=])?$

手机号码: ^ (13[0 - 9] | 14[5 | 7] | 15[0 | 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9] | 18[0 | 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9])\d{ 8 }$ 电话号码(0511 - 4405222、021 - 87888822):\d{ 3 } - \d{ 8 } | \d{ 4 } - \d{ 7 }

身份证号(15位、18位数字): ^ \d{ 15 } | \d{ 18 }$

短身份证号码(数字、字母x结尾): ^ ([0 - 9]) { 7, 18 }(x | X) ? $ 或 ^ \d{ 8,18 } | [0 - 9x]{ 8,18 } | [0 - 9X]{ 8,18 } ? $

帐号:(字母开头,允许5 - 16字节,允许字母数字下划线): ^ [a - zA - Z][a - zA - Z0 - 9_]{ 4,15 }$

密码:(以字母开头,长度在6~18之间,只能包含字母、数字和下划线): ^ [a - zA - Z]\w{ 5,17 }$

强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8 - 10之间): ^ (? = .\d)(? = .[a - z])(? = .*[A - Z]).{8, 10}$

日期格式: ^ \d{ 4 } - \d{ 1,2 } - \d{ 1,2 } 一年的12个月(01~09和1~12): ^ (0 ? [1 - 9] | 1[0 - 2])$

一个月的31天(01~09和1~31): ^ ((0 ? [1 - 9]) | ((1 | 2)[0 - 9]) | 30 | 31)$

xml文件: ^ ([a - zA - Z] + -? ) + [a - zA - Z0 - 9] + \\.\[x | X]\[m | M][l | L]$

中文字符的正则表达式:[\u4e00 - \u9fa5]

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

空白行的正则表达式:\n\s * \r(可以用来删除空白行)

HTML标记的正则表达式:<(\S* ? ) > >. ? < / \1> | <.* ? / > (复杂的嵌套标记依旧无能为力)

首尾空白字符的正则表达式: ^ \s * | \s * $或(^ \s*) | (\s * $) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等))

腾讯QQ号:[1 - 9][0 - 9]{ 4, } (腾讯QQ号从10000开始)

中国邮政编码:[1 - 9]\d{ 5 }(? !\d) (中国邮政编码为6位数字)

IP地址:\d + .\d + .\d + .\d + (提取IP地址时有用)

IP地址:((? : (? : 25[0 - 5] | 2[0 - 4]\d | [01] ? \d ? \d)\.) { 3 }(? : 25[0 - 5] | 2[0 - 4]\d | [01] ? \d ? \d))

例如匹配邮箱,直接拷贝,注意需要把空格去掉,并把单斜杆变成双斜杠

  1. #include<regex>
  2. using namespace std;
  3. int main()
  4. {
  5. //构造一个正则对象
  6. regex regx("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*.\\w+([-.]\\w+)*$");
  7. //字符串可以直接当作正则规则
  8. regex rege("ILoveYou");
  9. return 0;
  10. }

正则表达式的使用

做匹配

调用函数即可:bool regex_match(string str,regex reg);
第一个参数是要匹配的字符串,第二个参数是正则规则 / 对象

返回值:满足要求返回true  不满足返回false

正则匹配,一定是完全匹配

  1. #include <regex>
  2. #include <iostream>
  3. using namespace std;
  4. void test_regex_match()
  5. {
  6. #if 0
  7. //构建正则规则
  8. regex reg("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
  9. //用户输入邮箱
  10. string userName;
  11. while (1)
  12. {
  13. cout << "请输入一个邮箱:";
  14. cin >> userName;
  15. //传入参数
  16. bool result = regex_match(userName, reg);
  17. if (result)
  18. {
  19. cout << "正确邮箱" << endl;
  20. break;
  21. }
  22. }
  23. #endif
  24. //正则匹配一定是完全匹配
  25. string str = "ILoveyou1314";
  26. regex reg("[a-z0-9]+"); //小写字母或者数字多个
  27. if (regex_match(str, reg))
  28. {
  29. cout << "匹配" << endl;
  30. }
  31. else
  32. {
  33. cout << "不匹配" << endl; //打印不匹配 由于 IL 不满足正则规则
  34. }
  35. //大小写问题 提供带参构造方式 构造对象的时候可以忽略大小写-> 枚举类型
  36. regex reg2("[a-z0-9]+", regex_constants::icase);
  37. if (regex_match(str, reg2))
  38. {
  39. cout << "匹配" << endl;
  40. }
  41. else
  42. {
  43. cout << "不匹配" << endl;
  44. }
  45. //字符串也可以直接充当正则规则-> 必须要完全一样
  46. regex reg3("ILoveyou");
  47. if (regex_match(str, reg3))
  48. {
  49. cout << "匹配" << endl;
  50. }
  51. else
  52. {
  53. cout << "不匹配" << endl;
  54. }
  55. }
  56. int main()
  57. {
  58. test_regex_match();
  59. test_regex_replace();
  60. test_regex_search();
  61. return 0;
  62. }

正则替换

string regex_replace(string str,regex reg, string newstr);

第一个参数是要匹配的字符串,第二个参数是正则规则 / 对象,第三个参数是要把满足规则的替换成某一个新的字符

返回值:返回一个新的字符串

regex_constants 类 | Microsoft Docs

  1. void test_regex_replace()
  2. {
  3. string str = "ILoveyou1314520IMissyou520me";
  4. //把字符串中多个数字替换成"我爱你"
  5. regex reg("\\d+");
  6. cout << "str:" << regex_replace(str, reg, "我爱你") << endl;
  7. //原字符串不变
  8. cout << "oldstr:" << str << endl;
  9. //如何控制替换
  10. //1.只替换第一次出现的 加一个替换标准
  11. cout << "only first:" << regex_replace(str, reg, "我爱你", regex_constants::format_first_only) << endl;
  12. //2.不拷贝
  13. cout << "no copy:" << regex_replace(str, reg, "我爱你", regex_constants::format_no_copy) << endl;
  14. //3.默认方式
  15. cout<<"default:"<< regex_replace(str, reg, "我爱你", regex_constants::format_default) << endl;
  16. //4.sed格式规则
  17. cout << "sed:" << regex_replace(str, reg, "我爱你", regex_constants::format_sed) << endl;
  18. }
  19. /* 输出 */
  20. str:ILoveyou我爱你IMissyou我爱你me
  21. oldstr:ILoveyou1314520IMissyou520me
  22. only first:ILoveyou我爱你IMissyou520me
  23. no copy:我爱你我爱你
  24. default:ILoveyou我爱你IMissyou我爱你me
  25. sed:ILoveyou我爱你IMissyou我爱你me

正则截取处理字符串

bool regex_search(string str,smatch result,regex reg);

第一个参数是要匹配的字符串,第二个参数 smatch 用来保存捕获到的结果,第三个参数是正则表达式对象

返回值:bool 类型

using smatch  = match_results<string::const_iterator>;

smatch 存储捕获到的字符串的前缀和后缀

假设匹配到 1314,前缀就是 ILoveyou,后缀就是 IMissyou520me

如果没有后缀,获取的就是空字符,写一个循环判断后缀是否为空即可,如果不为空,就一直做截取,就可以把每一个匹配到的都截取出来

  1. void test_regex_search()
  2. {
  3. //正常截取处理匹配项
  4. string str = "ILoveyou1314IMissyou520me";
  5. //存储结果
  6. smatch result;
  7. //捕获处理-> 捕获多个数字
  8. bool flag = regex_search(str, result, regex("\\d+"));
  9. if (flag)
  10. {
  11. cout << "size:" << result.size() << endl;
  12. //匹配到的字符串存储在result中
  13. for (int i = 0; i < result.size(); i++)
  14. {
  15. //获取匹配到字符串
  16. cout << result.str() << endl;
  17. }
  18. //匹配到的字符串的前缀
  19. cout << "pre:" << result.prefix() << endl;
  20. //匹配到的字符串的后缀
  21. cout << "suf:" << result.suffix() << endl;
  22. }
  23. cout << "str:" << str << endl;
  24. //把每一块找到的都截取出来 result.suffix作为循环条件去持续截取即可
  25. // srgex_iterator
  26. regex rule("\\d+");
  27. //构建位置:原字符串开始位置 原字符串结束位置 这一串按照rule正则规则去截取
  28. sregex_iterator pos(str.begin(), str.end(), rule);
  29. //无参构造代表结束
  30. sregex_iterator end; //end_of_iterator
  31. //当前位置不等于结束位置
  32. while (pos != end)
  33. {
  34. //获取数据
  35. cout << pos->str() << endl;
  36. pos++;
  37. }
  38. //拆解字符串
  39. //sregex_token_iterator(iterator begin,iteartor end,regex regex, int flag);
  40. //flag: 0 存储所有匹配的,-1 存储所有不匹配的
  41. regex regexRule("\\d+");
  42. //原字符串开始位置 原字符串结束位置 规则 标记
  43. sregex_token_iterator Begin(str.begin(), str.end(), regexRule, 0);
  44. //无参构造代表结束
  45. sregex_token_iterator End;
  46. while (Begin != End)
  47. {
  48. //获取数据
  49. cout << Begin->str() << endl;
  50. Begin++;
  51. }
  52. cout << endl;
  53. }
  54. /* 输出 */
  55. size:1
  56. //匹配到的字符串
  57. 1314
  58. //前缀
  59. pre:ILoveyou
  60. //后缀
  61. suf:IMissyou520me
  62. str:ILoveyou1314IMissyou520me
  63. //把后续满足条件的每一部分都截取出来
  64. 1314
  65. 520
  66. //获取所有匹配的-> 按照正则规则把每一部分都拆解出来
  67. 1314
  68. 520
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/530868
推荐阅读
相关标签
  

闽ICP备14008679号