C++11正则表达式 ECMAScript文法

突然想写个爬虫,然后发现,如果有正则表达式,会方便些。

C++11提供了Regex类.可以用来完成:

1.Match: 将整个输入拿来比对(匹配)某个正则表达式。

2.Search:查找“与正则表达式吻合”的子序列。

3.Tokenize:正则表达式作为分割器,得到分割器之前的字符串。

4.Replace:将与正则表达式吻合之的子序列替换掉

主要函数有: regex_match(),regex_search(),regex_replace();

主要对象:sregex_iterator,sregex_token_iterator,regex,smatch

例子:

[[:alpha:]][[:alnum:]]* 表示,以_或字母开头,后面接着任意个_或字母的组合

[123]?[0-9].1?[0-9].20[0-9]{2} 表示german format,如 24.12.2010

C++11默认使用 ECMAScript 文法,告诉你怎么构造正则表达式

表示式 意义
. newline以外的任何字符
[...] ...字符中的任何一个
[^...] ...字符之外的任何一个
[ [:charclass:]] 指定字符串类charclass中的一个(见下表)
\n,\t,\f,\r,\v 一个newline,tabulator,form feed,carriage return,vertical tab
\xhh,\uhhh 一个十六进制字符或Unicode字符
* 前一个字符或群组,任意次数
? 前一个字符或群组,可有可无
+ 前一个字符或群组,至少一次
{n} 前一个字符或群组,n次
{n,} 前一个字符或群组,至少n次
{n,m} 前一个字符或群组,至少n次,至多m次
...|... 在 | 之前或之后的pattern,合并左边和右边,(.|\n)*表示任意字符和任意换行
(...) 设定群组(group)
\1,\2,\3 第n个group(第一个group的索引为1)
\b 一个正字词边界,字词的起点或终点,不知道什么意思
\B 一个负字词的边界,字词的非起点或非终点
^ 一行的起点
$ 一行的终点
字符类 缩写 转义 效果
[[:alnum:]] 一个字母或者数字
[[:alpha:]] 一个字母
[[:blank:]] 一个space或者tab
[[:cntrl:]] 一个控制字符
[[:digit:]] [[:d:]] \d 一个数字
\D 一个非数字
[[:graph:]] 可打印非空白字符,相当于[[:alnum:][:punct:]]
[[:lower:]] 一个小写字母
[[:print:]] 一个可打印字符,包括空白字符
[[:punct:]] 一个标点符号字符,但非space,digit,letter
[[:space:]] \s 一个空白字符
\S 一个非空白字符
[[:upper:]] 一个大写字母
[[:xdigit:]] 一个十六进制数字
\w 一个字母、数字或下划线
\W 一个非字母、非数字

附上一个测试例子:

#include <regex>
#include <iostream>
#include <string>
#include <iomanip>
#include <algorithm>

using namespace std;

void out(bool b){
    cout << ( b? "found" : "not found") << endl;
}

void regex1();
void regex2();
void regex3();
void regex4();
void regex5();
void regex6();

int main(){
    //regex1();
    //regex2();
    //regex3();
    //regex4();
    //regex5();
    //regex6();

    string data = "1994-06-25\n"
                  "2015-09-13\n"
                  "2015 09 13\n";
    smatch m;
    regex reg("(\\d{4})[- ](\\d{2})[- ](\\d{2})");
    //sregex_iterator pos(data.cbegin(),data.cend(),regex("(\\d{4})[- ](\\d{2})[- ](\\d{2})"));
    sregex_iterator pos(data.cbegin(),data.cend(),reg);
    sregex_iterator end;
        for( ; pos!=end ;pos++){
            cout << pos->str() << " ";
            cout << pos->str(1) << " " <<pos->str(2) <<" " << pos->str(3) << endl;
        }



    system("pause");
    return 0;
}

/*
 * regex_replace(string,reg1,reg2)
 * 将reg1匹配到的子串,用reg2替换掉
 */
void regex6(){
    string data = "<person>\n"
        "<first>Nico</first>\n"
        "<last>Josuttis</last>\n"
        "</person>\n";
    regex reg("<(.*)>(.*)</(\\1)>");

    cout << regex_replace(data,reg,"<$1 value=\"$2\"/>") << endl;

    string res2;

    regex_replace (back_inserter(res2),
                   data.begin(),data.end(),
                   reg,
                   "<$1 value=\"$2\"/>",
                   regex_constants::format_no_copy 
                   | regex_constants::format_first_only);
    cout << res2 << endl;
}

/*
 * sregex_token_iteartor 分割器
 * 详情看函数输出,比如,通过这个,可以取出下面的名字
 */
void regex5(){
    string data = "<person>\n"
        "<first>Nico</first>\n"
        "<last>Josuttis</last>\n"
        "</person>\n";
    regex reg("<(.*)>(.*)</(\\1)>");

    sregex_token_iterator pos(data.cbegin(),data.cend(),reg,0);
    sregex_token_iterator end;

    for(; pos!=end;pos++){
        cout << "match:    "<<pos->str() << endl;
    }
    cout<< endl;

    string names = "nico,jim,helmut,paul,tim,john paul,rita";
    regex sep("[ \t\n]*[,;.][ \t\n]*");
    sregex_token_iterator p(names.cbegin(),names.cend(),sep,-1);
    sregex_token_iterator e;
    for(; p!=e;p++){
        cout << "name:    "<<*p << endl;
    }
}

/*
 * sregex_iterator 迭代器,通过这样个来遍历所以满足的子串
 * 注意传进去的 begin,end 必须是const 所以使用 cbegin()
 */
void regex4(){
    string data = "<person>\n"
        "<first>Nico</first>\n"
        "<last>Josuttis</last>\n"
        "</person>\n";
    regex reg("<(.*)>(.*)</(\\1)>");

    sregex_iterator pos(data.cbegin(),data.cend(),reg);
    sregex_iterator end;
    for(;pos != end;++pos){
        cout << "match:    "<< pos->str(0) << endl;
        cout << "tag:    "<< pos->str(1)<< endl;
        cout << "value    "<< pos->str(2) << endl;
    }

    sregex_iterator beg(data.cbegin(),data.cend(),reg);
    for_each(beg,end,[](const smatch& m){
        cout << "match:    "<< m.str() << endl;
        cout << "tag:    "<< m.str(1)<< endl;
        cout << "value    "<< m.str(2) << endl;
    });
}

/*
 *  bool regex_search(string , smatch ,regex )
 *  对整个字符串,用这个regex进行匹配,找到第一个满足的子串,
 *  通过前面的例子,可以发现 m.suffix() 指得是,满足子串后面的,
 *  一个字符的索引,所以,通过一个循环,可以不断找出后面满足的
 */
void regex3(){
    string data = "<person>\n"
        "<first>Nico</first>\n"
        "<last>Josuttis</last>\n"
        "</person>\n";
    regex reg("<(.*)>(.*)</(\\1)>");

    auto pos = data.cbegin();
    auto end = data.cend();

    smatch m;

    for(; regex_search(pos,end,m,reg);pos = m.suffix().first){
        cout << "match:        "<<m.str() << endl;
        cout << "tag:        "<<m.str(1) << endl;
        cout << "value:  " << m.str(2) << endl;
        cout << "m.prefix():    "<<m.prefix().str() << endl;
        cout << "m.suffix():    "<<m.suffix().str() << endl;
    }
}

/*
 *  bool regex_search(string , smatch ,regex )
 *  对整个字符串,用这个regex进行匹配,找到第一个满足的子串,
 *  下面是通过smatch 获取子串内容的方法,索印对应群组
 */
void regex2(){
    string data = "XML tag: <tag-name>the value</tag-name>.";
    cout << "data:        "<<data << "\n\n";

    smatch m;
    bool found = regex_search(data,m,regex("<(.*)>(.*)</(\\1)>"));

    cout << "m.empty():        "<<boolalpha << m.empty() << endl;
    cout << "m.size():        "<<m.size() << endl;
    if(found){
        cout << "m.str():        "<<m.str() << endl;
        cout << "m.length():        "<<m.length()<<endl;
        cout << "m.position():        "<<m.position()<<endl;
        cout << "m.prefix().str():  "<<m.prefix().str()<< endl;
        cout << "m.suffix().str():  "<<m.suffix().str() << endl;
        cout << endl;

        for(int i = 0;i<m.size();i++){
            cout << "m["<<i<<"].str():        " << m[i].str() << endl;
            cout << "m.str("<<i << "):        " << m.str(i) << endl;
            cout << "m.position(" << i << "):        "<<m.position(i)<<endl;
        }
        cout << endl;

        cout << "matches:" << endl;
        for(auto pos = m.begin();pos!=m.end();pos++){
            cout << " "<< *pos << " ";
            cout << "(length:  " << pos->length() << ")" << endl;
        }
    }
}


/*
 *  bool regex_match(string , regex )
 *  对整个字符串,用这个regex进行匹配,会匹配最大满足的字符串
 */
void regex1(){
    regex reg1("<.*>.*</.*>");
    bool found = regex_match("<tag>value</tag>",reg1);
    out(found);

    regex reg2("<(.*)>.*</\\1>");
    found = regex_match("<tag>value</tag>",reg2);
    out(found);

    regex reg3("<\\(.*\\)>.*</\\1>",regex_constants::grep);
    found = regex_match("<tag>value</tag>",reg3);
    out(found);

    found = regex_match("<tag>value</tag>",regex("<(.*)>.*</\\1>"));
    out(found);

    cout << endl;

    found = regex_match("XML tag: <tag>value</tag>",
        regex("<(.*)>.*</\\1>"));
    out(found);

    found = regex_match("XML tag: <tag>value</tag>",
        regex(".*<(.*)>.*</\\1>"));
    out(found);

    found = regex_search("XML tag: <tag>value</tag>",
        regex("<(.*)>.*</\\1>"));
    out(found);

    found = regex_search("XML tag: <tag>value</tag>",
        regex(".*<(.*)>.*</\\1>"));
    out(found);
}

原文链接: https://www.cnblogs.com/cycxtz/p/4804115.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/221841

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午11:27
下一篇 2023年2月13日 上午11:27

相关推荐