在C++編程中,有一點(diǎn)讓人挺遺憾的就是C++尚不支持正則表達(dá)式,這讓很多用戶(hù)為了編寫(xiě)支持正則表達(dá)式程序而不得不放棄C++。然而,Boost.Regex庫(kù)填補(bǔ)了C++在這方面的空白,它使C++很好的支持各種引擎的正則表達(dá)式。
結(jié)合我的學(xué)習(xí),逐步分析Boost.Regex庫(kù)。
……
Boost.Regex默認(rèn)使用Perl正則表達(dá)式,關(guān)于Perl正則表達(dá)式的使用,這里就不多說(shuō)明了,可以參考相關(guān)資料。
Boost的正則表達(dá)式封裝在boost::basic_regex對(duì)象中,與std::basic_string一樣,boost::basic_regex表示的是一族類(lèi),也與std::basic_string一樣typedef了幾個(gè)特例:
typedef basic_regex<char> regex;
typedef basic_regex<wchar>wregex;
Boost.Regex的幾個(gè)中重要的成員函數(shù)人如下:
1. explicit basic_regex(const CharT* p,flag_type regex_constants::normal);
該構(gòu)造函數(shù)接受一個(gè)包含正則表達(dá)式的字符序列,以及一個(gè)表示正則表達(dá)式所選的參數(shù)信息——例如是否大小寫(xiě)或使用什么引擎的正則表達(dá)式。這里注意,如果傳遞的字符序列是無(wú)效的正則表達(dá)式,則會(huì)拋出異常regex_error。
2. bool emply()const;
該成員函數(shù)檢測(cè)basic_regex示例是否包含有效的正則表達(dá)式。
3. unsigned mark_count() const;
該成員函數(shù)返回該basic_regex示例中的正則表達(dá)式包含的有標(biāo)記的子表達(dá)式的個(gè)數(shù)。
4. flag_type flags()const;
該函數(shù)返回一個(gè)位掩碼,其中包含basic_regex所設(shè)置的選項(xiàng)標(biāo)志。具體標(biāo)志選項(xiàng)有:icase—忽略字符大小寫(xiě)和JavaScript—regex使用JavaScript語(yǔ)法
另外,Boost.Regex定義了幾個(gè)自由函數(shù),實(shí)現(xiàn)正則表達(dá)式的匹配查詢(xún)及修改:
1. 判斷正則表達(dá)式時(shí)候匹配整個(gè)字符串
1
template <typename CharT,typename Allocator,typename traits>
2
3
bool regex_match(
4
5
const CharT*,
6
7
match_result<const chart*,Allocator>&m,
8
9
const basic_regex<CharT,traits>& reg,
10
11
match_flag_type flags=match_default);
12
2. 查找字符串中與正則表達(dá)式匹配的子序列
template <typename CharT,typename Allocator,typename traits>

bool regex_rearch(

const CharT*,

match_result<const chart*,Allocator>&m,

const basic_regex<CharT,traits>& reg,

match_flag_type flags=match_default);

3. 查找字符串中所有正則表達(dá)式的匹配,并根據(jù)參數(shù)fmt格式化所匹配的串
template <typename CharT,typename Allocator,typename traits>

basic_string<CharT > regex_replace(

const basic_string<CharT >& s,

const basic_regex<CharT,traits>& reg,

const basic_string<CharT >& fmt,

match_flag_type flags=match_default);

使用說(shuō)明
1. 創(chuàng)建regex對(duì)象:
Include<boost/regex.hpp>

regex reg(“(.*)”);

2. regex_match
該函數(shù)用來(lái)對(duì)一個(gè)字符串的完全匹配,在很多校驗(yàn)信息中可以廣泛使用,具體使用示例見(jiàn)附后的測(cè)試代碼
3. regex_rearch
說(shuō)到這個(gè)函數(shù),必須要說(shuō)明下boost.match_result。 regex_rearch在執(zhí)行查找時(shí),通過(guò)一個(gè)match_result類(lèi)型的對(duì)象來(lái)報(bào)告匹配的自表達(dá)式。
match_result主要封裝了一個(gè)std::vector<sub_match<<…>> >類(lèi)型的對(duì)象,而sub_match類(lèi)繼承自std::pair,主要記錄匹配的結(jié)果信息。關(guān)于match_result和sub_match的詳細(xì)了解可以閱讀boost設(shè)計(jì)源碼:
使用示例查看附后的測(cè)試源碼。
4. regex_replace
該函數(shù)根據(jù)指定的fmt格式化通過(guò)正則表達(dá)式匹配的子串。需要注意的是,該函數(shù)不會(huì)修改原字符串,只是將格式化后的結(jié)果返回。具體使用示例見(jiàn)附后測(cè)試源碼。
5. regex_iterator
通過(guò)多次調(diào)用regex_rearch我們可以處理所有滿(mǎn)足匹配的字串。但是,Regex庫(kù)還給我們提供了一個(gè)更優(yōu)雅的方法——即通過(guò)regex_iterator。通過(guò)字符串和正則表達(dá)式構(gòu)造regex_iterator的時(shí)候會(huì)構(gòu)建一個(gè)match_result的對(duì)象用于保存匹配結(jié)果信息,再通過(guò)重載++運(yùn)算符達(dá)到遍歷所有匹配信息的目的。關(guān)于regex_iterator的詳細(xì)了解可以參考Regex的設(shè)計(jì)源碼:
使用示例查看附后的測(cè)試源碼。
6. regex_token_iterator
與regex_iterator相似,Regex還提供了一個(gè)列舉與正則表達(dá)式不匹配的子表達(dá)式,就是regex_token_iterator。與stl的設(shè)計(jì)類(lèi)似,是通過(guò)迭代器適配器實(shí)現(xiàn)的。這個(gè)特性讓我們很容易的分割字符串。關(guān)于regex_token_iterator的詳細(xì)了解請(qǐng)查看Regex的設(shè)計(jì)源碼:
7.測(cè)試源碼
1
#include<iostream>
2
#include<string>
3
#include<cassert>
4
#include<boost/regex.hpp>
5
#include<vector>
6
#include<iterator>
7
8
bool validate_identify_card(const std::string &s)
{
9
boost::regex reg("\\d{17}[A-Z0-9]");
10
return boost::regex_match(s,reg);
11
}
12
class regex_callback
{
13
public:
14
template<typename T>
15
void operator()(const T& what)
{
16
std::cout<<what[1].str()<<std::endl;
17
}
18
};
19
20
int main()
{
21
{
22
boost::regex reg("\\d{3}([a-zA-Z]+).(\\d{2}|N/A)\\s\\1");
23
std::string correct="123Hello N/A Hello";
24
std::string incorrect="123Hello 12 hello";
25
assert(boost::regex_match(correct,reg)==true);
26
assert(boost::regex_match(incorrect,reg)==false);
27
}
28
{
29
std::string s="421124598608976345";
30
assert(validate_identify_card(s)==true);
31
}
32
{
33
boost::regex reg("(new)|(delete)");
34
boost::smatch m;
35
int new_counter=0,delete_counter=0;
36
std::string s="Calls to new must be followed by delete.Calling simply new results in a Leak!";
37
std::string::const_iterator it=s.begin();
38
std::string::const_iterator end=s.end();
39
while(boost::regex_search(it,end,m,reg))
{//這里參數(shù)必須是const屬性
40
if(m[1].matched)
{
41
std::cout<<"The expression(new) matched"<<std::endl;
42
new_counter++;
43
}
44
if(m[2].matched)
{
45
std::cout<<"The expression(delete) matched"<<std::endl;
46
delete_counter++;
47
}
48
it=m[0].second;
49
}
50
std::cout<<"new_counter="<<new_counter<<std::endl;
51
std::cout<<"delete_counter="<<delete_counter<<std::endl;
52
}
53
{//使用boost::regex_replace
54
boost::regex reg("(colo)(u)(r)",boost::regex::icase|boost::regex::perl);
55
std::string s="Colour,colour,color,colOurize";
56
s=boost::regex_replace(s,reg,"$1$3");//regex_replace不直接修改s的值,而是返回新值
57
std::cout<<s<<std::endl;
58
}
59
{//使用boost::regex_iterator迭代器輸出所有匹配項(xiàng)
60
boost::regex reg("(\\d+),?");
61
std::string s="1,2,3,4,5,6,7,85,ad2348(,hj";
62
boost::sregex_iterator it(s.begin(),s.end(),reg);
63
boost::sregex_iterator end;
64
for_each(it,end,regex_callback());
65
}
66
{
67
boost::regex reg("/");
68
std::vector<std::string> vec;
69
std::string s="Split/Vulue/Teather/Neusoft/Write/By/Lanwei";
70
boost::sregex_token_iterator it(s.begin(),s.end(),reg,-1);
71
boost::sregex_token_iterator end;
72
while(it!=end)
73
vec.push_back(*it++);
74
copy(vec.begin(),vec.end(),std::ostream_iterator<std::string>(std::cout,"\n"));
75
}
76
{
77
boost::smatch m;
78
boost::regex reg("(new)|(delete)");
79
std::string s="Calls to new must be followed by delete.Calling simply new results in a Leak!";
80
std::string::const_iterator it=s.begin();
81
std::string::const_iterator end=s.end();
82
while(boost::regex_search(it,end,m,reg))
{
83
std::cout<<"size="<<m.size()<<std::endl;
84
std::cout<<"m[-2]="<<m[-2]<<std::endl;
85
std::cout<<"m[-1]="<<m[-1]<<std::endl;
86
std::cout<<"m[0]="<<m[0]<<std::endl;
87
std::cout<<"m[1]="<<m[1]<<std::endl;
88
//std::cout<<"m[2].type="<<typeid(m[2].first).name()<<std::endl;
89
std::cout<<"m[2]="<<m[2]<<std::endl;
90
// std::cout<<"m[2].first="<<m[2].first<<std::endl;
91
//std::cout<<"m[2].second="<<m[2].second<<std::endl;
92
it=m[0].second;
93
}
94
}
95
return 0;
96
}
97
學(xué)習(xí)小結(jié)
關(guān)于Boost.Regex庫(kù)的初步學(xué)習(xí)暫時(shí)告以段落。這是個(gè)非常有用的庫(kù),打破了用戶(hù)只有通過(guò)POSIX C的API實(shí)現(xiàn)正則表達(dá)式的局限。然而,這是一個(gè)偉大的庫(kù)博大精深的庫(kù),以上的了解只不過(guò)的鳳毛麟角,其內(nèi)部還有很多的隱藏秘密需要花大量的時(shí)間去挖掘,探索。