1 常用类
1.2 basic_regex 类
定义:
template <class charT, class traits = regex_traits<charT> >
class basic_regex;
basic_regex生成和处理一个正则表达式,这个类的用法很简单,俱体用法参考文献[2]。
1.2 sub_match类
这个类处理一个子表达式的匹配结果,定义如下:
template <class BidirectionalIterator>
class sub_match : public std::pair<BidirectionalIterator, BidirectionalIterator>
{
public:
typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
bool matched;
... ...
};
这个类表示和处理一个子串匹配结果。
match成员变量指示匹配是否成功。
注意到了这个类是从std::pair派生的,所以它有first和second这两个数据成员,如果匹配成功,first保存匹配字符子串的开始位置,second保存匹配字符串的结束位置。
sub_match的其它信息请参考文献[2]。
1.3 match_results
这个类处理sub_match的std::vector集合,保存多个匹配子串的结果。
template <class BidiIterator, class Allocator>
class match_results
{
private:
typedef std::vector<sub_match<BidiIterator> > vector_type;
typedef sub_match<BidiIterator> value_type;
private:
vector_type m_subs; // subexpressions
};
从上面的定义可以看出,这个类主要处理std::vector<sub_match<BidiIterator> > m_subs。这个类在下面要介绍的几个接口函数中要用到。
掌握了match_results大体结构就很容易理解它的作用。其它操作信息可以参考文献[2]。
2 常用算法
2.1 算法1——regex_match
regex_match(..)是一个全局模板函数,是boost::regex最基本用法。它作用是根据正则表达式确定整个字符序列是否符合一定的格式要求,模式由正则表达式确定。它最常用的地方是输入合法性的检验。
原型1:
template <class BidirectionalIterator, class Allocator, class charT, class traits>
bool regex_match(
BidirectionalIterator first,
BidirectionalIterator last,
match_results<BidirectionalIterator, Allocator>& m,
const basic_regex <charT, traits>& e,
match_flag_type flags = match_default);
first, last确定要匹配的目标序列,m是存放匹配的结果(见3.2.3),e就是输入的正则表达式,flags是匹配标识。返回值如果是true,则说明匹配成功;flase,说明不匹配。
上面这个算法函数包含一个匹配结果参数;一般情况下,用这个算法的时候,我们只要得到是否匹配结果就行了。boost::regex同样提供一个重载的函数:
原型2:
template <class BidirectionalIterator, class charT, class traits>
bool regex_match(
BidirectionalIterator first,
BidirectionalIterator last,
const basic_regex <charT, traits>& e,
match_flag_type flags = match_default);
与上一个重载函数相比,就少了一个match_results<BidirectionalIterator, Allocator>& m, 用起来更方便。regex_match还有几个重函数,只是参数有变化,总得用法和上面介绍的两个函数是一样的。
最后要指出的是regex_match是匹配整个字符序列是否符输入的正则表达式的要求;如果我们找出字符序列哪些子序列符合输入的正则表达式的要求,那就要用regex_search算法。regex_seach(..)就是下节要介绍的一个模板算法。
2.2 算法2——regex_search
regex_search是用boost::regex最常用到的模板算法。它的作用是字符序列中哪些子序列是匹配输入的正则表达式的。它的函数原型与regex_match差不多,只是在用法复杂了一些。
原型1:
template <class BidirectionalIterator,
class Allocator, class charT, class traits>
bool regex_search(
BidirectionalIterator first,
BidirectionalIterator last,
match_results<BidirectionalIterator, Allocator>& m,
const basic_regex<charT, traits>& e,
match_flag_type flags = match_default);
参数first和last确定要匹配的目标序列,m存放匹配结果,e就是输入的正则表达式, flags是匹配标识。
如果本次匹配成功,返回true;否返回的是false。
regex_search还有几个重载函数,用法与上面的相同,或者更简单,所以在这里不作介绍。它们的原型请参考文献[2]。
上面介绍的两种模板算法基本上可以满足正则表达式应用的要求。boost::regex还包含其它一些算法,在某些应用中可以发挥作用,俱体用法请参考文献[2]。
3 用法举例
上面介绍正则表达式语法、basic_regex以及regex_match、regex_search两个模板算法。现在就根据这些知识实现两个有意义的算法。
3.1 regex_match
给出一个卡号验证程序,这个程序在文献[4]中可以找到。
#include <iostream>
#include <string>
#include <boost/regex.hpp>
// 验证卡号是否与正则表达式匹配
bool validate_card_format(const std::string& s)
{
static const boost::regex e("(//d{4 }[- ]){3}//d{4}");
return boost::regex_match(s, e);
}
int main()
{
std::string s[4] = { "0000111122223333", "0000 1111 2222 3333",
"0000-1111-2222-3333", "000-1111-2222-3333", };
int i;
for (i = 0; i < 4; ++i)
{
std::cout << "validate_card_format(/"" << s[i] << "/") returned "
<< validate_card_format(s[i]) << std::endl;
}
return 0;
}
3.2 regex_search
下面程序参考了文献[4],作用是输入有2个子表达式的正则表达式,获得匹配结果以及匹配结果在整个序列中的开始索引。
const char* re = "(人)|(a)";
boost::regex expression(re, boost::regex_constants::normal);
typedef std::pair<std::string, int> pair_type;
typedef std::vector<pair_type> vec_type;
void search(const std::string& file, vec_type& vv)
{
std::string::const_iterator start, end;
start = file.begin();
end = file.end();
boost::match_results<std::string::const_iterator> what;
boost::match_flag_type flags = boost::match_default | boost::match_any;
vec_type v1; // contain full expression
vec_type v2; // contain (人) sub expression
vec_type v3; // contain (a) sub expression
while (boost::regex_search(start, end, what, expression, flags))
{
pair_type r;
std::string::const_iterator temp = end;
if (what[0].matched)
{
r.first = std::string(what[0].first, what[0].second);
r.second = what[0].first - file.begin();
v1.push_back(r);
temp = what[0].second;
}
if (what[1].matched) //
{
r.first = string(what[1].first, what[1].second);
r.second = what[1].first - file.begin();
v2.push_back(r);
if (temp - what[1].second > 0)
temp = what[1].second;
}
if (what[2].matched)
{
r.first = string(what[2].first, what[2].second);
r.second = what[2].first - file.begin();
v3.push_back(r);
if (temp - what[2].second > 0)
temp = what[2].second;
}
start = temp;
flags = boost::match_default | boost::match_any;
}
vv.push_back(v1);
vv.push_back(v2);
vv.push_back(v3);
}
上面的代码是与易懂为原则,所以代码写得比较松散。
4 对各种编码的支持
在实际应用开发中,有几种常用的编码方案,包括针对中文编码的GB2312、GB18030,UTF7、UTF8等,还有统一编码方案Unicode。
regex.hpp中有下面两行代码:
typedef basic_regex<char> regex;
typedef basic_regex<wchar_t> wregex;
中文编码的正则表达式用regex实现就行了;而对于Unicode编码用wregex实现。在这里要说明一下,wchar_t*并不是Unicode字符串。俱体什么是Unicode可以参考文献[5]。
5 参考文献
[1] www.boost.org boost库的官方网站,这套库包含许多有用的组件;
[2] boost_1_32_0 boost::regex附带文档;
[3] boost_1_32_0 boost::regex实现源码;
[4] boost_1_32_0 boost::regex附带examples;
[5] www.unicode.org 在这里可以找什么是unicode的主题。