正则表达式能方便处理文本问题,比如验证,匹配,查找,替换等。而boost xpressive提供动态和静态方式,静态方式类似于boost.spirit语法分析器,使用操作符重载生成编译器的表达式对象,可以在编译器进行正则表达式的语法检查。动态方式以字符串作为表达式对象,在运行时进行语法检查和处理。通常我们不必关心那种方式,因为在boost中它们已经融合,所以两者可以混用。
Example:
1. "a." 可能表示ab, a0
2. "(a*)(b|c+)" 两个子表达式,任意数量的a,然后接一个b或者一个以上的c,如:aaab,aaccc
3. "[abc]?.\{\}" abc三个字符之一可以出现0次或一次,然后是任意字符,接一个{},如:a={},c2{}
xpressive中重要的三个类:basic_regex,match_results,sub_match
template <typename BidiIter>
struct basic_regex
{
basic_regex();
basic_regex(basic_regex const &);
regex_id_type regex_id() const;//唯一ID
std::size_t mark_count() const;//子表达式个数
void swap(basic_regex &);
static basic_regex compile(InputRange const & pat); //静态工厂函数
};
typedef basic_regex<std::string::const_iterator> sregex;
typedef basic_regex<char const *> cregex;
注意最后的sregex和cregex,分别用户操作std::string,和操作字符数组。而basic_regex的核心功能是静态成员函数compile(),它是一个工厂方法,可以根据正则表达式参数创建一个basic_regex对象。
template <typename BidiIter>
struct match_results
{
size_type size() const;//子表达式个数
bool empty() const;
template <typename Sub>
const_reference operator[](Sub const & i) const; //获取子表达式
};
typedef match_results<std::string::const_iterator> smatch;
typedef match_results<char const *> cmatch;
match_results为正则表达式的匹配结果提供一个类似容器的视图,operator[]返回第i个子表达式。
template <typename BidiIter>
struct sub_match : public std::pair
{
string_type str() const;
difference_type length() const;
bool operator!() const;
int compare(string_type const &) const;//字符串比较
bool matched;
};
自由函数regex_match()用来检查一个字符串是否完全匹配一个正则表达式,返回一个bool结果。
bool regex_match(String, basic_regex const & re);
bool regex_match(String, match_results& what, basic_regex const & re);
思路:身份证前六位是地区编码,中间8为是年月日,最后4位数字可能有一个X。
前6位:\d{6}
中8位:年:(1|2)\d{3},月:(0|1)\d,天:[0-3]\d
后四位:\d{3}(X|\d)
//***********************************************************
//FUNCTION:: personal identity match
// C++ 98: \\d{6}((1|2)\\d{3})((0|1)\\d)([0-3]\\d)(\\d{3}(X|\\d))
// C++ 11: R"---\d{6}((1|2)\d{3})((0|1)\d)([0-3]\d)(\d{3}(X|\d))---" Or R"---(\d{6}(1|2)\d{3}(0|1)\d[0-3]\d\d{3}(X|\d))---"
void personalIdentityMatch()
{
boost::xpressive::cregex Reg = boost::xpressive::cregex::compile("\\d{6}((1|2)\\d{3})((0|1)\\d)([0-3]\\d)(\\d{3}(X|\\d))", boost::xpressive::icase);忽略大小写
boost::xpressive::cmatch What;
assert(boost::xpressive::regex_match("999555197001019999", What, Reg));//What保存为()子表达式集合
for (auto e : What)
{
std::cout << "[" << e << "] " ;
}
std::cout << std::endl;
std::cout << "Date: " << What[1] << What[3] << What[5] << std::endl;
}
注意\是转义字符,所以想用其需要再添加一个 \ 。regex_match()要求输入字符串必须要与正则表达式完全匹配。
//***********************************************************
//FUNCTION::
void fullMatchMail()
{
const char* pMail = "[email protected]";
boost::xpressive::cmatch What;
boost::xpressive::cregex Reg = boost::xpressive::cregex::compile("(\\w+)@(\\w+).(\\w+)", boost::xpressive::icase);
assert(boost::xpressive::regex_match(pMail, What, Reg));
for (auto e : What)
{
std::cout << "[" << e << "] " ;
}
}
regex_search与regex_match相似,但是不要求完全匹配,只要一个子表达式匹配就返回true。
regex_search可以替代string_algo的contains,starts_with,ends_with算法:
std::string Str("readme.TXT");
boost::xpressive::sregex start_reg = boost::xpressive::sregex::compile("^re");
boost::xpressive::sregex end_reg = boost::xpressive::sregex::compile("txt$", boost::xpressive::icase);
assert(boost::xpressive::regex_search(Str, start_reg));
assert(boost::xpressive::regex_search(Str, end_reg ));
assert(boost::xpressive::regex_search(Str, boost::xpressive::cregex::compile("me")));
使用正则表达式匹配字符串,再用指定格式替换:
String regex_replace(String, basic_regex const & re, Format);
Format可以是简单字符串,也可以是一个符合ECMA-262定义的带格式的字符串。注意返回值是一个字符串的拷贝。
regex_replace替换string_algo的修剪和删除算法
//***********************************************************
//FUNCTION::
void regexReplace()
{
std::string Str("2010 Happy new Year!!!");
boost::xpressive::sregex Reg1 = boost::xpressive::sregex::compile("^(\\d| )*");
boost::xpressive::sregex Reg2 = boost::xpressive::sregex::compile("!*$");
std::cout << boost::xpressive::regex_replace(Str, Reg1, "") << std::endl;
std::cout << boost::xpressive::regex_replace(Str, Reg2, "") << std::endl;
Str = boost::xpressive::regex_replace(Str, Reg1, "Y2000 ");
std::cout << Str << std::endl;
}
regex_iterator提高类似迭代器的视图(不是容器),可以变量正则表达式的匹配结果。
template <typename BidiIter>
struct regex_iterator
{
typedef match_results value_type;
regex_iterator(BidiIter, BidiIter, basic_regex const & );
value_type const & operator*() const;
value_type const & operator->() const;
regex_iterator & operator++();
regex_iterator operator(int);
};
构造函数传入分词区间和正则表达式对象,之后可以反复调用operator++,使用*或者->获取匹配的结果match_results对象
//***********************************************************
//FUNCTION::
void regexIterator()
{
std::string Str("Power-bomb, power-suit, pOWER-beam, all items \n");
boost::xpressive::sregex Reg = boost::xpressive::sregex::compile("power-(\\w{4})", boost::xpressive::icase);
boost::xpressive::sregex_iterator Pos(Str.begin(), Str.end(), Reg);
boost::xpressive::sregex_iterator End;
while (Pos != End)
{
std::cout << "[" << (*Pos)[0] << "]" ;//operator*返回一个match_results对象
++Pos;
}
std::cout << std::endl;
}
模板类regex_token_iterator提供了强大的分词迭代器,类基本和regex_iterator一致,区别如下:
...
regex_token_iterator(BidiIter, BidiIter, basic_regex_const &, match_flag_type args);
...
//***********************************************************
//FUNCTION::
void regexTokenIterator()
{
char* pStr = "*Link*||+Mario+||Zelda!!!||Metroid";
//查找所有单词,无视标点符号
boost::xpressive::cregex Reg = boost::xpressive::cregex::compile("\\w+", boost::xpressive::icase);
boost::xpressive::cregex_token_iterator Pos(pStr, pStr+strlen(pStr), Reg);
while (Pos != boost::xpressive::cregex_token_iterator())
{
std::cout << "[" << *Pos << "]";
++Pos;
}
std::cout << std::endl;
//使用分割正则表达式
boost::xpressive::cregex SpiltReg = boost::xpressive::cregex::compile("\\|\\|", boost::xpressive::icase);
Pos = boost::xpressive::cregex_token_iterator(pStr, pStr+strlen(pStr), SpiltReg, -1);
while (Pos != boost::xpressive::cregex_token_iterator())
{
std::cout << "[" << *Pos << "]";
++Pos;
}
std::cout << std::endl;
}
接口几乎一致,设计思想不同:
【参考资料】
【1】Boost程序库完全开发指南
【2】http://my.oschina.net/lingluonianhua/blog/211788?fromerr=5JdsKJ0k