正则表达式是一种十分强大的文本分析工具,其使用了一套复杂的语法规则,解决了文本处理领域的绝大多数问题,诸如验证,匹配,查找以及替换,今天我们就来学习boost库下的xpressive这个先进,灵活的正则表达式库吧,在介绍之前,我们需要了解下正则表达式的一些基础知识:
1)点号开头可以匹配任意的单个字符
2)^匹配行的开头
3)$匹配行的末尾
4)()用于定义一个正则表达式匹配的子元素(子表达式),可以被引用或重复
5)*表示前面的元素可以重复任意多次
6)+表示前面的元素可以重复一次或多次
7)?表示前面的元素可以重复0次或1次
8){}表示手工指定元素重复的次数
9)[]定义字符集合,可以列出单个字符,也可以定义范围或者集合的补集
10)\是转义字符,特殊字符转义后与自身匹配
11)|表示逻辑或的概念,匹配它两侧的元素之一
了解了下正则表达式基本规则之后,我们来看看xpressive的一些基础知识,xpressive库提供了两种使用方法:静态和动态,静态的方式类似于spirit,通过使用运算符重载生成编译期的表达式对象,其可以在编译期对语法规则进行检查,而动态的方法主要是在运行期对语法规则进行检查,与boost.regex和python中的re模块很相似,这两种方法不是对立的,在xpressive库中使用较多的主要是动态的方法,因此,我们在此仅就动态的方法进行阐述,首先来看看xpressive库里的几个比较重要的类吧,分别是:basic_regex,match_results和sub_match。
1. basic_regex类
模板类basic_regex时xpressive库的核心类,它封装了正则表达式的解析和编译,下面就来看看basic_regex的类摘要吧,代码如下:
template<typename BidiIter> struct basic_regex { basic_regex(); basic_regex(basic_regex<BidiIter>const& s); regex_id_type regex_id()const; std::size_type make_count() const; void swap(basic_regex<BidiIter>&); static basic_regex<BidiIter> compile(InputRange const& p); }; typedef basic_regex<std::string::const_iterator> sregex; typedef basic_regex<char const*> cregex;
在basic_regex类摘要中,regex_id函数返回正则表达式的唯一标志,而make_count函数则返回表达式中匹配的子表达式的个数,compile函数是basic_regex的核心函数,它是一个工厂函数,根据正则表达式参数来创建一个basic_regex对象,其有很多的重载的形式,但是最常用的是一个字符串类型,它必须是一个合法的正则表达式,否则会运行出错
2. match_results类
match_results类也是xpressive库里的一个很重要的类,保存了正则表达式匹配的结果,其类的摘要如下:
template<tyname BidiIter> struct match_results { size_type size() const; bool empty() const; template<typename sub> const_refence operator[](sub const& i)const; }; typedef match_results<std::string::const_iterator> smatch; typedef match_results<char const*> cmatch;
match_results类为正则表达式匹配结构提供了一个类似容器的视图,使用size函数和empty函数判断匹配结果中子表达式的数量,operator[]返回第i个子表达式。
3. sub_match类
这个模板类是xpressive库中的类似迭代器对的对象,其继承std::pair,可以把它当成字符串区间表示,类摘要如下:
template<typename BidiIter> struct sub_match : public std::pair<BidiIter,BidiIter> { string_type str() const; difference_type length() const; bool operator!() const; int compare(string_type const&)const; bool matched; };
简要的介绍完了xpressive库中的几个重要的类之后,我们就来看看几个简答的测试用例,来熟悉下基本的用法,代码如下:
1. 测试一
#include <boost/xpressive/xpressive_dynamic.hpp> #include <iostream> using namespace boost; using namespace boost::xpressive; using namespace std; int main() { cregex reg = cregex::compile("\\d{4}"); assert(regex_match("1234",reg)); assert(!regex_match("123d",reg)); assert(!regex_match("adgc",reg)); return 0; }
2. 测试二
#include <boost/xpressive/xpressive_dynamic.hpp> #include <boost/typeof/typeof.hpp> #include <iostream> using namespace boost; using namespace boost::xpressive; using namespace std; int main() { std::string express = "\\d{6}((1|2)\\d{3})((0|1)\\d)([0-3]\\d)(\\d{3}(X|\\d))"; cregex reg = cregex::compile(express,icase); assert(regex_match("999999197002031999",reg)); assert(regex_match("99999919871021999X",reg)); cmatch what; assert(regex_match("99999919900325999x",what,reg)); for(BOOST_AUTO(pos,what.begin());pos != what.end();++pos) { cout<<"["<<*pos<<"]"<<endl; } return 0; }
接下来,我们再来看看几个比较常用的操作,一个regex_search,一个是regex_replace,首先来看看regex_search,其与regex_match最大的区别就是regex_match需要输入的串与正则表达式完全匹配,而regex_search则是检查输入表达式是否包含正则表达式,相比而言,regex_search要比regex_match更灵活,其声明如下:
bool regex_search(string,basic_regex const& re); bool regex_search(string,match_result& what, basic_regex const& re);
其实形式与regex_match相同,但是其不要求完全匹配,只要找到有匹配的子串就返回true。实例代码如下:
#include <boost/xpressive/xpressive_dynamic.hpp> #include <boost/typeof/typeof.hpp> using namespace boost::xpressive; using namespace boost; using namespace std; int main() { const char* str = "there is a POWER-suit item"; cregex reg = cregex::compile("(POWER)-(.{4})",icase); cmatch what; regex_search(str,what,reg); for(BOOST_AUTO(pos,what.begin());pos != what.end();pos++) cout<<*pos<<endl; return 0; }
测试结果:
POWER-suit
POWER
suit
在xpressive库中替换函数regex_replace,其首先通过正则表达式查找匹配,然后使用指定的字符串格式来替换,具体的声明如下:
string regex_replace(string,basic_regex const& re,Fomat);
前两个字符串与regex_match类似,第三个参数则是指定了替换的格式,下面就来看看几个简单的测试用例吧,熟悉下regex_replace的用法,代码如下:
#include <boost/xpressive/xpressive_dynamic.hpp> #include <iostream> using namespace boost; using namespace boost::xpressive; using namespace std; int main() { string str("zmyer.txt"); sregex reg1 = sregex::compile("(.*)(er)"); sregex reg2 = sregex::compile("(z)(.)(r)"); cout<<regex_replace(str,reg1,"manual")<<endl; cout<<regex_replace(str,reg1,"$1you")<<endl; cout<<regex_replace(str,reg2,"$&$&")<<endl; return 0; }
测试结果:
manual.txt
zmyyou.txt
zmyer.txt
总结
本篇博文简要地分析了下boost::xexpressive库,这个库较为精简,并且使用也是很方便的,在实际应用中也偶尔用到,在boost里面还有个更加完整的正则表达式库——regex,本篇只是一个引子,在后续的博文中,我们会有针对性使用正则表达式做一些有意义的东西,好了,本篇博文到此结束,谢谢
如果需要,请注明转载,多谢
原文:http://blog.csdn.net/zmyer/article/details/19151113