忽然想寫個爬蟲,而後發現,若是有正則表達式,會方便些。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); }