现在的位置: 首页 > 综合 > 正文

Boost.Regex库学习笔记

2017年11月25日 ⁄ 综合 ⁄ 共 5246字 ⁄ 字号 评论关闭

在C++编程中,有一点让人挺遗憾的就是C++尚不支持正则表达式,这让很多用户为了编写支持正则表达式程序而不得不放弃C++。然而,Boost.Regex库填补了C++在这方面的空白,它使C++很好的支持各种引擎的正则表达式。

结合我的学习,逐步分析Boost.Regex库。

……

Boost.Regex默认使用Perl正则表达式,关于Perl正则表达式的使用,这里就不多说明了,可以参考相关资料。

Boost的正则表达式封装在boost::basic_regex对象中,与std::basic_string一样,boost::basic_regex表示的是一族类,也与std::basic_string一样typedef了几个特例:

typedef basic_regex<char> regex;

typedef basic_regex<wchar>wregex;

Boost.Regex的几个中重要的成员函数人如下:

1. explicit basic_regex(const CharT* p,flag_type regex_constants::normal);

该构造函数接受一个包含正则表达式的字符序列,以及一个表示正则表达式所选的参数信息——例如是否大小写或使用什么引擎的正则表达式。这里注意,如果传递的字符序列是无效的正则表达式,则会抛出异常regex_error。

2. bool emply()const;

该成员函数检测basic_regex示例是否包含有效的正则表达式。

3. unsigned mark_count() const;

该成员函数返回该basic_regex示例中的正则表达式包含的有标记的子表达式的个数。

4. flag_type flags()const;

该函数返回一个位掩码,其中包含basic_regex所设置的选项标志。具体标志选项有:icase—忽略字符大小写和JavaScript—regex使用JavaScript语法

另外,Boost.Regex定义了几个自由函数,实现正则表达式的匹配查询及修改:

1. 判断正则表达式时候匹配整个字符串

template <typename CharT,typename Allocator,typename traits>

bool regex_match(

const CharT*, 

match_result<const chart*,Allocator>&m,

const basic_regex<CharT,traits>& reg,

match_flag_type flags=match_default);

2. 查找字符串中与正则表达式匹配的子序列

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. 查找字符串中所有正则表达式的匹配,并根据参数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);

使用说明

1. 创建regex对象:

Include<boost/regex.hpp>

regex reg(“(.*)”);

2. regex_match

该函数用来对一个字符串的完全匹配,在很多校验信息中可以广泛使用,具体使用示例见附后的测试代码

3. regex_rearch

说到这个函数,必须要说明下boost.match_result。 regex_rearch在执行查找时,通过一个match_result类型的对象来报告匹配的自表达式。

match_result主要封装了一个std::vector<sub_match<<…>> >类型的对象,而sub_match类继承自std::pair,主要记录匹配的结果信息。关于match_result和sub_match的详细了解可以阅读boost设计源码:

使用示例查看附后的测试源码。

4. regex_replace

该函数根据指定的fmt格式化通过正则表达式匹配的子串。需要注意的是,该函数不会修改原字符串,只是将格式化后的结果返回。具体使用示例见附后测试源码。

5. regex_iterator

通过多次调用regex_rearch我们可以处理所有满足匹配的字串。但是,Regex库还给我们提供了一个更优雅的方法——即通过regex_iterator。通过字符串和正则表达式构造regex_iterator的时候会构建一个match_result的对象用于保存匹配结果信息,再通过重载++运算符达到遍历所有匹配信息的目的。关于regex_iterator的详细了解可以参考Regex的设计源码:

使用示例查看附后的测试源码。

6. regex_token_iterator

与regex_iterator相似,Regex还提供了一个列举与正则表达式不匹配的子表达式,就是regex_token_iterator。与stl的设计类似,是通过迭代器适配器实现的。这个特性让我们很容易的分割字符串。关于regex_token_iterator的详细了解请查看Regex的设计源码:

7.测试源码

#include<iostream>
#include<string>
#include<cassert>
#include<boost/regex.hpp>
#include<vector>
#include<iterator>

bool validate_identify_card(const std::string &s){
 boost::regex reg("\\d{17}[A-Z0-9]");
 return boost::regex_match(s,reg);
}
class regex_callback{
 public:
 template<typename T>
 void operator()(const T& what){
 std::cout<<what[1].str()<<std::endl;
 }
};

int main(){
 {
 boost::regex reg("\\d{3}([a-zA-Z]+).(\\d{2}|N/A)\\s\\1");
 std::string correct="123Hello N/A Hello";
 std::string incorrect="123Hello 12 hello";
 assert(boost::regex_match(correct,reg)==true);
 assert(boost::regex_match(incorrect,reg)==false);
 }
 {
 std::string s="421124598608976345";
 assert(validate_identify_card(s)==true);
 }
 {
 boost::regex reg("(new)|(delete)");
 boost::smatch m;
 int new_counter=0,delete_counter=0;
 std::string s="Calls to new must be followed by delete.Calling simply new results in a Leak!";
 std::string::const_iterator it=s.begin();
 std::string::const_iterator end=s.end();
 while(boost::regex_search(it,end,m,reg)){//这里参数必须是const属性
 if(m[1].matched){
 std::cout<<"The expression(new) matched"<<std::endl;
 new_counter++;
 }
 if(m[2].matched){
 std::cout<<"The expression(delete) matched"<<std::endl;
 delete_counter++;
 }
 it=m[0].second;
 }
 std::cout<<"new_counter="<<new_counter<<std::endl;
 std::cout<<"delete_counter="<<delete_counter<<std::endl;
 }
 {//使用boost::regex_replace
 boost::regex reg("(colo)(u)(r)",boost::regex::icase|boost::regex::perl);
 std::string s="Colour,colour,color,colOurize";
 s=boost::regex_replace(s,reg,"$1$3");//regex_replace不直接修改s的值,而是返回新值
 std::cout<<s<<std::endl;
 }
 {//使用boost::regex_iterator迭代器输出所有匹配项
 boost::regex reg("(\\d+),?");
 std::string s="1,2,3,4,5,6,7,85,ad2348(,hj";
 boost::sregex_iterator it(s.begin(),s.end(),reg);
 boost::sregex_iterator end;
 for_each(it,end,regex_callback());
 }
 {
 boost::regex reg("/");
 std::vector<std::string> vec;
 std::string s="Split/Vulue/Teather/Neusoft/Write/By/Lanwei";
 boost::sregex_token_iterator it(s.begin(),s.end(),reg,-1);
 boost::sregex_token_iterator end;
 while(it!=end)
 vec.push_back(*it++);
 copy(vec.begin(),vec.end(),std::ostream_iterator<std::string>(std::cout,"\n"));
 }
{
 boost::smatch m;
 boost::regex reg("(new)|(delete)");
 std::string s="Calls to new must be followed by delete.Calling simply new results in a Leak!";
 std::string::const_iterator it=s.begin();
 std::string::const_iterator end=s.end();
 while(boost::regex_search(it,end,m,reg)){
 std::cout<<"size="<<m.size()<<std::endl;
 std::cout<<"m[-2]="<<m[-2]<<std::endl;
 std::cout<<"m[-1]="<<m[-1]<<std::endl;
 std::cout<<"m[0]="<<m[0]<<std::endl;
 std::cout<<"m[1]="<<m[1]<<std::endl;
 //std::cout<<"m[2].type="<<typeid(m[2].first).name()<<std::endl;
 std::cout<<"m[2]="<<m[2]<<std::endl;
 // std::cout<<"m[2].first="<<m[2].first<<std::endl;
 //std::cout<<"m[2].second="<<m[.second<<std::endl;
 it=m[0].second;
 }
 }
 return 0;
}

学习小结

关于Boost.Regex库的初步学习暂时告以段落。这是个非常有用的库,打破了用户只有通过POSIX C的API实现正则表达式的局限。然而,这是一个伟大的库博大精深的库,以上的了解只不过的凤毛麟角,其内部还有很多的隐藏秘密需要花大量的时间去挖掘,探索。

原文:http://www.cppblog.com/tianbianlan/archive/2009/07/24/91015.html

抱歉!评论已关闭.