突然想寫個爬蟲,然后發現,如果有正則表達式,會方便些。
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); }
