boost正则库匹配ASII编码的中文、全角字符示例

首先,boost正则库(regex)不支持形如 [0-9] 这样的表达式,貌似会崩溃。

 

   现在查网上正则匹配中文的例子,都是讲用 \uFF00-\uFFFF ; 拜托,\u是unicode编码,能用于我常用的ansii编码(如GB18030,GBK,GB2312等等)吗?举例时也不说清楚。

 

   再次查看正则语法,发现 \xnn 比较有用,\x匹配ASCII编码中十六进制代码为nn的字符,注意,是单个字符,因此,对于双字节的全角,我们需要用两个\x才能匹配一个全角字符。列如下(下文实例全部使用ANSII编码):

 

   全角数字:0123456789 (\xA3[\xB0-\xB9])+ , 0是\xA3\xB0

   全角小写字母:az (\xA3[\xE1-\xFA])+, a是\xA3\xE1 z是\xA3\xFA

   全角大写字母:AZ (\xA3[\xC1-\xDA])+ ,A是\xA3\xC1 Z是\xA3\xDA

 

    其他汉字也类似,有需要的可以自己查查编码。 不知道汉字对应的ANSII编码?使用URALEDIT32,输入汉字后按CTRL+H,就可以看到16进制的编码。

==================================

boost::regex简单用法

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]。

posted on 2010-03-19 13:32  cy163  阅读(3400)  评论(0编辑  收藏  举报

导航