|
Posted on 2011-05-04 19:15 點(diǎn)點(diǎn)滴滴 閱讀(16565) 評(píng)論(0) 編輯 收藏 引用 所屬分類(lèi): 02 編程語(yǔ)言
注意使用Boost.Regex需要預(yù)先編譯
完整編譯請(qǐng)參考本站編譯Boost的文章 如果只要編譯Regex庫(kù),有兩種方法(參考鏈接):
- 在Boost根目錄下運(yùn)行bjam --toolset=<編譯器名> --with-regex 其它參數(shù)
- 到<boost>\libs egex\build里,找到對(duì)應(yīng)編譯器的makefile,然后make -f xxxx.mak
使用
Boost.Regex手里有七種武器和兩****寶 其中的七種武器是:
regex_match 函數(shù)
regex_search 函數(shù)
regex_replace 函數(shù)
regex_format 函數(shù)
regex_grep 函數(shù)
regex_split 函數(shù)
RegEx 類(lèi)
每種武器都又有諸多變化(每個(gè)函數(shù)都分別以C字符串類(lèi)型、std::string類(lèi)型、迭代器類(lèi)型作為參數(shù)重載),不過(guò)后面四種武器因年久失修已不建議使用. 兩****寶是:
regex_iterator 迭代器
regex_token_iterator 迭代器
這兩****寶是整個(gè)Boost.Regex的靈魂,用熟它們以后那是“摘花飛葉即可傷人”啊~~
回到正題,下面邊寫(xiě)邊學(xué)。
所需頭文件:
#include <boost/regex.hpp>
示例代碼:
先準(zhǔn)備一個(gè)測(cè)試用的數(shù)據(jù)備用,如果各位有雅興可以參考本站的另一篇文章《Google Testing》使用Google Testing框架來(lái)做這個(gè)實(shí)驗(yàn),花一樣時(shí)間學(xué)兩樣啊~~
- #include <iostream>
- #include <boost/regex.hpp>
-
- using namespace std;
- int main(int argc, char* argv[])
- {
-
-
- const char *szReg = "(\\w+)://((\\w+\\.)*\\w+)((/\\w*)*)(/\\w+\\.\\w+)?";
- const char *szStr = "http://www.cppprog.com/2009/0112/48.html";
-
-
-
-
- cin.get();
- }
1.字符串匹配
要確定一行字符串是否與指定的正則表達(dá)式匹配,使用regex_match。 下面這個(gè)代碼可以驗(yàn)證szStr字串(定義在上面)是否與szReg匹配。
- {
- boost::regex reg( szReg );
- bool r=boost::regex_match( szStr , reg);
- assert(r);
- }
boost::regex的構(gòu)造函數(shù)中還可以加入標(biāo)記參數(shù)用于指定它的行為,如:
-
- boost::regex reg1( szReg, boost::regex::perl|boost::regex::icase );
-
- boost::regex reg2( szReg, boost::regex::extended );
下面這個(gè)代碼不僅驗(yàn)證是否匹配,而且可以從中提取出正則表達(dá)式括號(hào)對(duì)應(yīng)的子串。
- {
- boost::cmatch mat;
- boost::regex reg( szStr );
- bool r=boost::regex_match( szStr, mat, reg);
- if(r)
- {
-
- for(boost::cmatch::iterator itr=mat.begin(); itr!=mat.end(); ++itr)
- {
-
- cout << itr->first-szStr << ' ' << itr->second-szStr << ' ' << *itr << endl;
- }
- }
-
- if(mat[4].matched) cout << "Path is" << mat[4] << endl;
- }
其中,boost::cmatch是一個(gè)針對(duì)C字符串的特化版本,它還有另三位兄弟,如下:
typedef match_results<const char*> cmatch;
typedef match_results<std::string::const_iterator> smatch;
typedef match_results<const wchar_t*> wcmatch;
typedef match_results<std::wstring::const_iterator> wsmatch;
可以把match_results看成是一個(gè)sub_match的容器,同時(shí)它還提供了format方法來(lái)代替regex_format函數(shù)。 一個(gè)sub_match就是一個(gè)子串,它從std::pair<BidiIterator, BidiIterator>繼承而來(lái),這個(gè)迭代器pair里的first和second分別指向了這個(gè)子串開(kāi)始和結(jié)尾所在位置。同時(shí),sub_match又提供了str(),length()方法來(lái)返回整個(gè)子串。
2.查找字符串
regex_match只驗(yàn)證是否完全匹配,如果想從一大串字符串里找出匹配的一小段字符串(比如從網(wǎng)頁(yè)文件里找超鏈接),這時(shí)就要使用regex_search了。 下面這段代碼從szStr中找數(shù)字
- {
- boost::cmatch mat;
- boost::regex reg( "\\d+" );
- if(boost::regex_search(szStr, mat, reg))
- {
- cout << "searched:" << mat[0] << endl;
- }
- }
3.替換
regex_replace提供了簡(jiǎn)便的方法來(lái)部分替換源字符串 正則表達(dá)式中,使用$1~$9(或\1~\9)表示第幾個(gè)子串,$&表示整個(gè)串,$`表示第一個(gè)串,$'表示最后未處理的串。
- {
- boost::regex reg( szReg );
- string s = boost::regex_replace( string(szStr), reg, "ftp://$2$5");
- cout << "ftp site:"<< s << endl;
- }
正則表達(dá)式中,使用(?1~?9新字串)表示把第幾個(gè)子串替換成新字串,其中是S1()代表一個(gè)字串,S2的(?1)代表替換哪個(gè)字串,?0代表所有都要加上后面的字符串?1代表第一個(gè)替換成的字符串
- {
- string s1 = "(<)|(>)|(&)";
- string s2 = "(?1<)(?2>)(?3&)";
- boost::regex reg( s1 );
- string s = boost::regex_replace( string("cout << a&b << endl;"), reg, s2, boost::match_default | boost::format_all);
- cout << "HTML:"<< s << endl;
- }
4.使用regex_iterator查找
對(duì)應(yīng)于C字符串和C++字符串以及寬字符,regex_iterator同樣也有四個(gè)特化:
typedef regex_iterator<const char*> cregex_iterator;
typedef regex_iterator<std::string::const_iterator> sregex_iterator;
typedef regex_iterator<const wchar_t*> wcregex_iterator;
typedef regex_iterator<std::wstring::const_iterator> wsregex_iterator;
這個(gè)迭代器的value_type定義是一個(gè)match_results。
- {
- boost::regex reg( "\\d+" );
- boost::cregex_iterator itrBegin(szStr, szStr+strlen(szStr), reg);
- boost::cregex_iterator itrEnd;
- for(boost::cregex_iterator itr=itrBegin; itr!=itrEnd; ++itr)
- {
-
- cout << (*itr)[0].first-szStr << ' ' << (*itr)[0].second-szStr << ' ' << *itr << endl;
- }
- }
Boost.Regex也提供了make_regex_iterator函數(shù)簡(jiǎn)化regex_iterator的構(gòu)造,如上面的itrBegin可以寫(xiě)成:
itrBegin = make_regex_iterator(szStr,reg);
5.使用regex_token_iterator拆分字符串
它同樣也有四個(gè)特化,形式和上面類(lèi)似,就不再寫(xiě)一遍騙篇幅了。 這個(gè)迭代器的value_type定義是一個(gè)sub_match。
- {
- boost::regex reg("/");
- boost::cregex_token_iterator itrBegin(szStr, szStr+strlen(szStr), reg,-1);
- boost::cregex_token_iterator itrEnd;
- for(boost::cregex_token_iterator itr=itrBegin; itr!=itrEnd; ++itr)
- {
- cout << *itr << endl;
- }
- }
Boost.Regex也提供了make_regex_token_iterator函數(shù)簡(jiǎn)化regex_token_iterator的構(gòu)造,最后的那個(gè)參數(shù)-1表示以reg為分隔標(biāo)志拆分字符串,如果不是-1則表示取第幾個(gè)子串,并且可以使用數(shù)組來(lái)表示同時(shí)要取幾個(gè)子串,例如:
- {
- boost::regex reg("(.)/(.)");
- int subs[] = {1,2};
- boost::cregex_token_iterator itrBegin = make_regex_token_iterator(szStr,reg,subs);
- boost::cregex_token_iterator itrEnd;
- for(boost::cregex_token_iterator itr=itrBegin; itr!=itrEnd; ++itr)
- {
- cout << *itr << endl;
- }
- }
完整測(cè)試代碼:
- #include <iostream>
- #include <boost/regex.hpp>
-
- using namespace std;
- int main(int argc, char* argv[])
- {
-
-
- const char *szReg = "(\\w+)://((\\w+\\.)*\\w+)((/\\w*)*)(/\\w+\\.\\w+)?";
- const char *szStr = "http://www.cppprog.com/2009/0112/48.html";
-
- {
- boost::regex reg( szReg );
- bool r=boost::regex_match( szStr , reg);
- assert(r);
- }
-
- {
- boost::cmatch mat;
- boost::regex reg( szReg );
- bool r=boost::regex_match( szStr, mat, reg);
- if(r)
- {
-
- for(boost::cmatch::iterator itr=mat.begin(); itr!=mat.end(); ++itr)
- {
-
- cout << itr->first-szStr << ' ' << itr->second-szStr << ' ' << *itr << endl;
- }
- }
-
- if(mat[4].matched) cout << "Path is" << mat[4] << endl;
- }
-
- {
- boost::cmatch mat;
- boost::regex reg( "\\d+" );
- if(boost::regex_search(szStr, mat, reg))
- {
- cout << "searched:" << mat[0] << endl;
- }
- }
-
- {
- boost::regex reg( szReg );
- string s = boost::regex_replace( string(szStr), reg, "ftp://$2$5");
- cout << "ftp site:"<< s << endl;
- }
- {
- string s1 = "(<)|(>)|(&)";
- string s2 = "(?1<)(?2>)(?3&)";
- boost::regex reg( s1 );
- string s = boost::regex_replace( string("cout << a&b << endl;"), reg, s2, boost::match_default | boost::format_all);
- cout << "HTML:"<< s << endl;
- }
-
- {
- boost::regex reg( "\\d+" );
- boost::cregex_iterator itrBegin = make_regex_iterator(szStr,reg);
- boost::cregex_iterator itrEnd;
- for(boost::cregex_iterator itr=itrBegin; itr!=itrEnd; ++itr)
- {
-
- cout << (*itr)[0].first-szStr << ' ' << (*itr)[0].second-szStr << ' ' << *itr << endl;
- }
- }
-
- {
- boost::regex reg("/");
- boost::cregex_token_iterator itrBegin = make_regex_token_iterator(szStr,reg,-1);
- boost::cregex_token_iterator itrEnd;
- for(boost::cregex_token_iterator itr=itrBegin; itr!=itrEnd; ++itr)
- {
- cout << *itr << endl;
- }
- }
-
- {
- boost::regex reg("(.)/(.)");
- int subs[] = {1,2};
- boost::cregex_token_iterator itrBegin = make_regex_token_iterator(szStr,reg,subs);
- boost::cregex_token_iterator itrEnd;
- for(boost::cregex_token_iterator itr=itrBegin; itr!=itrEnd; ++itr)
- {
- cout << *itr << endl;
- }
- }
-
-
- cin.get();
- return 0;
- }
|