C++11正則表達式 ECMAScript文法

忽然想寫個爬蟲,而後發現,若是有正則表達式,會方便些。ios

C++11提供了Regex類.能夠用來完成:git

1.Match: 將整個輸入拿來比對(匹配)某個正則表達式。正則表達式

2.Search:查找「與正則表達式吻合」的子序列。函數

3.Tokenize:正則表達式做爲分割器,獲得分割器以前的字符串。測試

4.Replace:將與正則表達式吻合之的子序列替換掉spa

 

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

主要對象:sregex_iterator,sregex_token_iterator,regex,smatchorm

 

例子:對象

[_[:alpha:]][_[:alnum:]]* 表示,以_或字母開頭,後面接着任意個_或字母的組合blog

[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);
}
相關文章
相關標籤/搜索