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

时间:2022-07-26
本文章向大家介绍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-25n"
                  "2015-09-13n"
                  "2015 09 13n";
    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("[ tn]*[,;.][ tn]*");
    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 << "nn";

    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);
}