Boost.Regex库 正则表达式

时间:2022-09-09 00:15:59

在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.       判断正则表达式时候匹配整个字符串

 

 1template <typename CharT,typename Allocator,typename traits>
 2
 3bool regex_match(
 4
 5const CharT*,
 6
 7match_result<const chart*,Allocator>&m,
 8
 9const basic_regex<CharT,traits>& reg,
10
11match_flag_type flags=match_default);
12
 

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.测试源码

                   

 1#include<iostream>
 2#include<string>
 3#include<cassert>
 4#include<boost/regex.hpp>
 5#include<vector>
 6#include<iterator>
 7
 8bool validate_identify_card(const std::string &s){
 9    boost::regex reg("\\d{17}[A-Z0-9]");
10    return boost::regex_match(s,reg);
11}
12class 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
20int 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)){//这里参数必须是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迭代器输出所有匹配项
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
 

       学习小结

Boost.Regex库使用实例

  1. #include <iostream>
  2. #include <boost/regex.hpp>
  3.  
  4. using namespace std;
  5. int main(int argc, char* argv[])
  6. {    //( 1 )   ((  3  )  2 )((  5 )4)(    6    )   
  7.     //(/w+)://((/w+/.)*/w+)((//w*)*)(//w+/./w+)?
  8.     //^协议://网址(x.x...x)/路径(n个/字串)/网页文件(xxx.xxx)
  9.     const char *szReg = "(//w+)://((//w+//.)*//w+)((///w*)*)(///w+//.//w+)?";
  10.     const char *szStr = "http://www.cppprog.com/2009/0112/48.html";
  11.  
  12.     {    //字符串匹配
  13.         boost::regex reg( szReg );
  14.         bool r=boost::regex_match( szStr , reg);
  15.         assert(r);
  16.     }
  17.  
  18.     {    //提取子串
  19.         boost::cmatch mat;
  20.         boost::regex reg( szReg );
  21.         bool r=boost::regex_match( szStr, mat, reg);
  22.         if(r) //如果匹配成功
  23.         {
  24.             //显示所有子串
  25.             for(boost::cmatch::iterator itr=mat.begin(); itr!=mat.end(); ++itr)
  26.             {
  27.                 //       指向子串对应首位置        指向子串对应尾位置          子串内容
  28.                 cout << itr->first-szStr << ' ' << itr->second-szStr << ' ' << *itr << endl;
  29.             }
  30.         }
  31.         //也可直接取指定位置信息
  32.         if(mat[4].matched) cout << "Path is" << mat[4] << endl;
  33.     }
  34.  
  35.     { //查找
  36.         boost::cmatch mat;
  37.         boost::regex reg( "//d+" );    //查找字符串里的数字
  38.         if(boost::regex_search(szStr, mat, reg))
  39.         {
  40.             cout << "searched:" << mat[0] << endl;
  41.         }
  42.     }
  43.  
  44.     { //替换
  45.         boost::regex reg( szReg );
  46.         string s = boost::regex_replace( string(szStr), reg, "ftp://$2$5");
  47.         cout << "ftp site:"<< s << endl;
  48.     }
  49.     { //替换2,把<>&转换成网页字符
  50.         string s1 = "(<)|(>)|(&)";
  51.         string s2 = "(?1&lt;)(?2&gt;)(?3&amp;)";
  52.         boost::regex reg( s1 );
  53.         string s = boost::regex_replace( string("cout << a&b << endl;"), reg, s2, boost::match_default | boost::format_all);
  54.         cout << "HTML:"<< s << endl;
  55.     }
  56.  
  57.     { //使用迭代器找出所有数字
  58.         boost::regex reg( "//d+" );    //查找字符串里的数字
  59.         boost::cregex_iterator itrBegin = make_regex_iterator(szStr,reg); //(szStr, szStr+strlen(szStr), reg);
  60.         boost::cregex_iterator itrEnd;
  61.         for(boost::cregex_iterator itr=itrBegin; itr!=itrEnd; ++itr)
  62.         {
  63.                 //       指向子串对应首位置        指向子串对应尾位置          子串内容
  64.                 cout << (*itr)[0].first-szStr << ' ' << (*itr)[0].second-szStr << ' ' << *itr << endl;
  65.         }
  66.     }
  67.  
  68.     { //使用迭代器拆分字符串
  69.         boost::regex reg("/");  //按/符拆分字符串
  70.         boost::cregex_token_iterator itrBegin = make_regex_token_iterator(szStr,reg,-1); //使用-1参数时拆分,使用其它数字时表示取第几个子串,可使用数组取多个串
  71.         boost::cregex_token_iterator itrEnd;
  72.         for(boost::cregex_token_iterator itr=itrBegin; itr!=itrEnd; ++itr)
  73.         {
  74.             cout << *itr << endl;
  75.         }
  76.     }
  77.  
  78.     { //使用迭代器拆分字符串2
  79.         boost::regex reg("(.)/(.)");  //取/的前一字符和后一字符(这个字符串形象貌似有点邪恶-_-)
  80.         int subs[] = {1,2};        // 第一子串和第二子串
  81.         boost::cregex_token_iterator itrBegin = make_regex_token_iterator(szStr,reg,subs); //使用-1参数时拆分,使用其它数字时表示取第几个子串,可使用数组取多个串
  82.         boost::cregex_token_iterator itrEnd;
  83.         for(boost::cregex_token_iterator itr=itrBegin; itr!=itrEnd; ++itr)
  84.         {
  85.             cout << *itr << endl;
  86.         }
  87.     }
  88.  
  89.  
  90.     cin.get();
  91.     return 0;
  92. }