zoukankan      html  css  js  c++  java
  • C++ 正则表达式示例

    一、正则表达式类对象

      C++标准库中提供了对正则表达式的支持,一下是常用的使用方法:

      1. regex 类:

        定义包含正则表达式的对象,如regex rx("a(b?)c");

      2. cmath 类:

        定义保存匹配结果的对象;

        当待搜索的字符串是char类型时,使用此类对象;

      3. smath 类:

        定义保存匹配结果的对象;

        当待搜索的字符串是string类型时,使用此类对象;

      4. 常用正则匹配函数:

        4.1 bool regex_match(...)

        判断是否准确匹配整个目标字符串,是目标字符串和正则表达式要完全匹配时才返回TRUE;

        如"abc"和"ab*c" 完全匹配,但是如果是"abcd"和"ab*c",虽然只有部分匹配(abc)但是返回是false;

        4.2 bool regex_search(...)

        在目标字符串中搜索一个匹配正则的字符串,如果搜索到了则返回true,否则返回false;

        4.3 regex_replace(...)

        用指定的字符串替换匹配到的字符串,默认是替换所有目标字符串中匹配到的字符串,加了format_first_only标志表示只替换第一次匹配到的字符串;

    二、使用示例

      

     1 #include <iostream>
     2 #include <sstream>
     3 #include <fstream>
     4 #include <string>
     5 #include <regex>
     6 
     7 using namespace std;
     8 
     9 int main(int argc, char * argv[])
    10 {
    11     const char * first = "abc"; //待匹配字符串
    12     const char * last = first + strlen(first);
    13     cmatch narrowMatch; //char *类型的对象来匹配保存结果
    14     regex rx("ab*c"); //定义包含正则表达式的对象
    15 
    16     // 注意:regex_match是目标字符串和正则表达式要完全匹配时才返回true.  
    17     // 如"abc"和"ab*c"完全匹配返回true,但是如果是"abcd"和"ab*c",虽然只有  
    18     // 部分匹配(abc)但是返回是false  
    19     // regex_match有多个重载函数,可以只有三个参数,不保存结果.  
    20     // 也可以有四个参数,第三个参数用来保存结果,一般情况下使用三个参数的就可以了  
    21     bool found = regex_match(
    22                                 first, //待匹配开始位置
    23                                 last, //待匹配的结束位置
    24                                 narrowMatch, // 保存结果
    25                                 rx //正则表达式
    26                                 );
    27 
    28     cout << found << endl;
    29     //cout << narrowMatch << endl; //错误
    30 
    31     string target2("Drizzle");
    32     regex rx2("(D\w+e)");
    33     smatch result;
    34     found = regex_match(
    35                             target2.cbegin(), //匹配开始 -->迭代器区间开始开始位置
    36                             target2.cend(), //匹配结束 -->迭代器区间结束位置 
    37                             result, //保存结果
    38                             rx2 //正则表达式
    39                             );
    40     cout << found << endl;
    41     //cout << result << endl; //错误
    42 }
     1 #include <iostream>
     2 #include <regex>
     3 #include <fstream>
     4 #include <string>
     5 #include <sstream>
     6 
     7 using namespace std;
     8 
     9 int main(void)
    10 {
    11     const char * first = "abcd";
    12     const char * last = first + strlen(first);
    13     cmatch mr; //保存匹配结果, 可打印
    14     regex rx("abc"); 
    15     std::regex_constants::match_flag_type fl = std::regex_constants::match_default; //匹配标志 
    16 
    17     // 给定目标字符串的起始和结束位置
    18     // 完全和正则表达式匹配,不同于regex_match()
    19     // 可打印正确匹配的结果,不同于regex_match()
    20     bool search1 = regex_search(first, first+1, rx, fl);
    21     cout << "search1: " << search1 << endl;
    22 
    23     bool search2 = regex_search(first, last, mr, rx);
    24     cout << "search2: " << search2 << "; mr: " << mr.str() << endl;
    25 
    26     // 给定待匹配的字符串(char类或string类)
    27     bool search3 = regex_search("a", //待匹配字符串 
    28                                 rx);
    29     cout << "search3: " << search3 << endl;
    30 
    31     bool search4 = regex_search("xabcd", mr, rx);
    32     cout << "search4: " << search4 << "; mr: " << mr.str() << endl;
    33 
    34     bool search5 = regex_search(string("a"), //待匹配对象,string类 
    35                                         rx);
    36     cout << "search5: " << search5 << endl;
    37 
    38     string st("abcabc");
    39     smatch mr2; //保存匹配结果,可打印
    40     bool search6 = regex_search(st, mr2, rx);
    41     cout << "search6: " << search6 << "; mr2: " << mr2.str() << endl;
    42 
    43     return 0;
    44 }
     1 #include <iostream>
     2 #include <sstream>
     3 #include <string>
     4 #include <regex>
     5 
     6 using namespace std;
     7 
     8 int main(void)
     9 {
    10     char buf[20];
    11     const char * first = "axayaz";
    12     const char * last = first + strlen(first);
    13 
    14     regex rx("a");
    15     string fmt("A");
    16     regex_constants::match_flag_type fonly = regex_constants::format_first_only;
    17 
    18     // 默认是替换所有目标字符串总匹配到的字符串
    19     // format_first_only标志表示只替换第一次匹配到的字符串
    20     // 输出替换后的字符串
    21     *regex_replace(
    22                     &buf[0], //被更改字符串的迭代器 
    23                     first, 
    24                     last,
    25                     rx,
    26                     fmt //要替换的字符串  
    27                     ) = '';
    28     cout << "replacement1: " << &buf[0] << endl;
    29 
    30     *regex_replace(
    31                     &buf[0],
    32                     first,
    33                     last,
    34                     rx,
    35                     fmt,
    36                     fonly //替换标志,在此表示只替换第一次匹配到的字符串  
    37                     ) = '';
    38     cout << "replacement2: " << &buf[0] << endl;
    39 
    40     string str("adaeaf");
    41     string replacement3 = regex_replace(
    42                                         str,
    43                                         rx,
    44                                         fmt
    45                                         );
    46     cout << "replacement3: " << replacement3 << endl;
    47 
    48     string replacement4 = regex_replace(
    49                                         str,
    50                                         rx,
    51                                         fmt,
    52                                         fonly
    53                                         );
    54     cout << "replacement4: " << replacement4 << endl;
    55 
    56     return 0;
    57 }
     1 #include <iostream>
     2 #include <regex>
     3 #include <fstream>
     4 #include <string>
     5 #include <sstream>
     6 
     7 using namespace std;
     8 
     9 int main(void)
    10 {
    11     const char * first = "abcd";
    12     const char * last = first + strlen(first);
    13     cmatch mr; //保存匹配结果, 可打印
    14     regex rx("abc"); 
    15     std::regex_constants::match_flag_type fl = std::regex_constants::match_default; //匹配标志 
    16 
    17     // 给定目标字符串的起始和结束位置
    18     // 完全和正则表达式匹配,不与待搜索字符串同长度,不同于regex_match()
    19     // 可打印正确匹配的结果,不同于regex_match()
    20     bool search1 = regex_search(first, first+1, rx, fl);
    21     cout << "search1: " << search1 << endl;
    22 
    23     bool search2 = regex_search(first, last, mr, rx);
    24     cout << "search2: " << search2 << "; mr: " << mr.str() << endl;
    25 
    26     // 给定待匹配的字符串(char类或string类)
    27     bool search3 = regex_search("a", //待匹配字符串 
    28                                 rx);
    29     cout << "search3: " << search3 << endl;
    30 
    31     bool search4 = regex_search("xabcd", mr, rx);
    32     cout << "search4: " << search4 << "; mr: " << mr.str() << endl;
    33 
    34     bool search5 = regex_search(string("a"), //待匹配对象,string类 
    35                                         rx);
    36     cout << "search5: " << search5 << endl;
    37 
    38     string st("abcabc");
    39     smatch mr2; //保存匹配结果,可打印
    40     bool search6 = regex_search(st, mr2, rx);
    41     cout << "search6: " << search6 << "; mr2: " << mr2.str() << endl;
    42 
    43     ///////////////////////////////4.regex_search(...)循环遍历字符串示例/////////////////////////  
    44     ///       --------->找到目标字符串中所有匹配的子串  
    45     ///       ####----->此示例中找到s串中所有以subj开头的单词,并打印出来  
    46     ///////////////////////////////////////////////////////////////////////////////////////////
    47     string s("this subject has a subjmarine as a subjsequence subjmite");
    48     smatch m;
    49     regex e("\b(subj)([^ ]*)/"); 
    50     while (regex_search(s, m, e))
    51     {
    52         cout << m.str() << endl;
    53         s = m.suffix().str();
    54     }
    55 
    56     return 0;
    57 }

     三、特殊字符及语法表达式

    参考:
    http://deerchao.net/tutorials/regex/regex.htm
    http://www.regexlab.com/zh/regref.htm
    http://www.cplusplus.com/reference/regex/ECMAScript/

    正则表达式(regular expression)就是用一个“字符串”来描述一个特征,然后去验证另一个“字符串”是否符合这个特征。比如 表达式“ab+” 描述的特征是“一个 ‘a’ 和 任意个 ‘b’ ”,那么 ‘ab’, ‘abb’, ‘abbbbbbbbbb’ 都符合这个特征。

    正则表达式可以用来:

    1. 验证字符串是否符合指定特征,比如验证是否是合法的邮件地址。
    2. 用来查找字符串,从一个长的文本中查找符合指定特征的字符串,比查找固定字符串更加灵活方便。
    3. 用来替换,比普通的替换更强大。

    从c++ 11开始,标准c++库在 里面提供了正则表达式的支持。默认的,c++ regex正则表达式使用的是ECMAScript语法。

    ECMAScript语法

    普通字符

    字母、数字、汉字、下划线、以及后边没有提到的特殊模式字符,都是”普通字符”。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。

    举例1:表达式 “c”,在匹配字符串 “abcde” 时,匹配结果是:成功;匹配到的内容是:”c”;匹配到的位置是:开始于2,结束于3。(注:下标从0开始还是从1开始,因当前编程语言的不同而可能不同)

    举例2:表达式 “bcd”,在匹配字符串 “abcde” 时,匹配结果是:成功;匹配到的内容是:”bcd”;匹配到的位置是:开始于1,结束于4。

    特殊模式字符

    特殊模式字符是在正则表达式中有特殊含义的字符,比如代表某些无法用字符串表达的字符或者代表一类字符。

    表达式 可匹配
    r 回车
    n 换行
    f 换页
    t 水平制表符
    v 数值制表符
    . 除了行结束符(LF CR LS PS)外所有字符(LF换行,CR回车,LS行分割,PS段落分割)
    d 0~9 中的任意一个数字
    D d的反面
    w 任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个
    W w的反面
    s 包括空格、制表符、换页符等空白字符的其中任意一个
    S s的反面

    字符类

    使用方括号 [ ] 包含一系列字符,能够匹配其中任意一个字符。用 [^ ] 包含一系列字符,则能够匹配其中字符之外的任意一个字符。同样的道理,虽然可以匹配其中任意一个,但是只能是一个,不是多个。

    表达式 可匹配
    [ab5@] 匹配 “a” 或 “b” 或 “5” 或 “@”
    [^abc] 匹配 “a”,”b”,”c” 之外的任意一个字符
    [f-k] 匹配 “f”~”k” 之间的任意一个字母
    [^A-F0-3] 匹配 “A”~”F”,”0″~”3″ 之外的任意一个字符

    举例1:表达式 “[bcd][bcd]” 匹配 “abc123” 时,匹配的结果是:成功;匹配到的内容是:”bc”;匹配到的位置是:开始于1,结束于3。

    举例2:表达式 “[^abc]” 匹配 “abc123” 时,匹配的结果是:成功;匹配到的内容是:”1″;匹配到的位置是:开始于3,结束于4。

    量词

    字符 次数
    * 0到无限次
    + 1到无限次
    ? 0到1次
    {int} int次
    {int,} int到无限次
    {min,max} 大于等于min次,小于等于max次

    举例1:表达式 “d+.?d*” 在匹配 “It costs $12.5” 时,匹配的结果是:成功;匹配到的内容是:”12.5″;匹配到的位置是:开始于10,结束于14。

    举例2:表达式 “go{2,8}gle” 在匹配 “Ads by goooooogle” 时,匹配的结果是:成功;匹配到的内容是:”goooooogle”;匹配到的位置是:开始于7,结束于17。

    默认的,这些量词都是贪婪的,就是他们会尽可能的去匹配最多的字符。在量词后面加上?,这些行为可以改成懒惰的。
    比如:”(a+).*”去匹配”aardvark”,得到结果是”aa”。
    “(a+?).*”去匹配”aardvark”,得到结果是”a”。

    贪婪与懒惰

    当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。

    有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:

    a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。

    懒惰限定符

    表达式 匹配
    *? 重复任意次,但尽可能的少
    +? 重复1次或更多次,但尽可能少重复
    ?? 重复0次或1次,但尽可能少重复
    {n,m}? 重复n到m次,但尽可能少重复
    {n,}? 重复n次以上,但尽可能少重复

    分组

    分组可以使量词作用在几个字符上。有两种分组:

    字符 描述 效果
    (subpattern) Group 创造反向引用
    (?:subpattern) Passive Group 不创造反向引用

    当分组创建了一个反向引用,分组内的子表达式会存储成一个子匹配。每个子匹配的都是以左括号出现次序为数字的索引。第一个子匹配是1,第二个是2,一次类推。这些子匹配可以用在后续的正则表达式中。

    选择

    模式中存在不同的可选部分。

    举例5:表达式 “Tom|Jack” 在匹配字符串 “I’m Tom, he is Jack” 时,匹配结果是:成功;匹配到的内容是:”Tom”;匹配到的位置是:开始于4,结束于7。匹配下一个时,匹配结果是:成功;匹配到的内容是:”Jack”;匹配到的位置时:开始于15,结束于19。

    举例6:表达式 “(gos*)+” 在匹配 “Let’s go go go!” 时,匹配结果是:成功;匹配到内容是:”go go go”;匹配到的位置是:开始于6,结束于14。

    举例7:表达式 “¥(d+.?d*)” 在匹配 “$10.9,¥20.5” 时,匹配的结果是:成功;匹配到的内容是:”¥20.5″;匹配到的位置是:开始于6,结束于10。单独获取括号范围匹配到的内容是:”20.5″。

    反向引用

    表达式在匹配时,表达式引擎会将小括号 “( )” 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候,小括号包含的表达式所匹配到的字符串可以单独获取。在实际应用场合中,当用某种边界来查找,而所要获取的内容又不包含边界时,必须使用小括号来指定所要的范围。

    其实,”小括号包含的表达式所匹配到的字符串” 不仅是在匹配结束后才可以使用,在匹配过程中也可以使用。表达式后边的部分,可以引用前面 “括号内的子匹配已经匹配到的字符串”。引用方法是 “” 加上一个数字。”1″ 引用第1对括号内匹配到的字符串,”2″ 引用第2对括号内匹配到的字符串……以此类推,如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 “(” 在前,那这一对就先排序号。

    举例1:表达式 “(‘|”)(.*?)(1)” 在匹配 ” ‘Hello’, “World” ” 时,匹配结果是:成功;匹配到的内容是:” ‘Hello’ “。再次匹配下一个时,可以匹配到 ” “World” “。

    举例2:表达式 “(w)1{4,}” 在匹配 “aa bbbb abcdefg ccccc 111121111 999999999” 时,匹配结果是:成功;匹配到的内容是 “ccccc”。再次匹配下一个时,将得到 999999999。这个表达式要求 “w” 范围的字符至少重复5次,点击测试 注意与 “w{5,}” 之间的区别。

    举例3:表达式 “<(w+)s*(w+(=(‘|”).*?4)?s*)*>.*?</1>” 在匹配 ”

    ” 时,匹配结果是成功。如果 ” ” 与 ”

    ” 不配对,则会匹配失败;如果改成其他配对,也可以匹配成功。

    断言

    断言是判断字符出现位置的条件,它本身不代表任何字符。

    字符 描述 匹配条件
    ^ 行开始 一行的开头或者紧跟行结束符后面
    $ 行结束 一行的末尾或者紧跟行结束前面
    b 字符边界 开头和结尾被认为是非字符
    B 非字符边界 开头和结尾被认为是非字符
    (?=subpattern) 正向预搜索匹配 正向预搜索匹配
    (?!subpattern) 正向预搜索不匹配 正向预搜索不匹配

    格式:”(?=xxxxx)”,在被匹配的字符串中,它对所处的 “缝隙” 或者 “两头” 附加的条件是:所在缝隙的右侧,必须能够匹配上 xxxxx 这部分的表达式。因为它只是在此作为这个缝隙上附加的条件,所以它并不影响后边的表达式去真正匹配这个缝隙之后的字符。这就类似 “b”,本身不匹配任何字符。”b” 只是将所在缝隙之前、之后的字符取来进行了一下判断,不会影响后边的表达式来真正的匹配。

    举例1:表达式 “Windows (?=NT|XP)” 在匹配 “Windows 98, Windows NT, Windows 2000” 时,将只匹配 “Windows NT” 中的 “Windows “,其他的 “Windows ” 字样则不被匹配。

    格式:”(?!xxxxx)”,所在缝隙的右侧,必须不能匹配 xxxxx 这部分表达式。

    举例3:表达式 “((?!bstopb).)+” 在匹配 “fdjka ljfdl stop fjdsla fdj” 时,将从头一直匹配到 “stop” 之前的位置,如果字符串中没有 “stop”,则匹配整个字符串。

    举例4:表达式 “do(?!w)” 在匹配字符串 “done, do, dog” 时,只能匹配 “do”。在本条举例中,”do” 后边使用 “(?!w)” 和使用 “b” 效果是一样的。

  • 相关阅读:
    架构设计中的方法学——迭代设计
    架构重构改善既有代码的设计
    架构如何为业务和技术“服务”(2)
    架构如何为业务和技术“服务”(1)
    选用面向领域的多层分布式架构(DDD风格架构)的理由
    传话游戏(2013编程之美全国挑战赛资格赛)
    2012年蓝桥杯软件设计大赛河南省初赛试题和答案
    最大值最下化
    NYOJ120 校园网络(强连通缩点targan算法)
    NYOJ176整数划分(二)
  • 原文地址:https://www.cnblogs.com/xiaofeiIDO/p/7892185.html
Copyright © 2011-2022 走看看