简介Boost.Regex

Posted on 2008-07-20 10:31 RichardHe 阅读(1069) 评论(0)  编辑 收藏 引用 所属分类: [转]

简介1
    正 则表达式(Regular expression)是一种在文本处理中经常用到的模式匹配的形式,可能许多用户熟悉Unix下的grep,sed,awk等工具或者perl语言,它 们都广泛地用到了正则表达式。传统的C++用户还受限于用POSIX C API's(Portable operateing system interface standard)来操作正则表达式,而regex++已经提供了这些API's,虽然它不一定是使用POSIX C 正则表达式库的最好方法。比如regex++能处理宽字符字符串(wide character strings),或者搜索、替换操作(在某种意义上类似于sed或perl),这些在传统的C 库中是不能实现的。
类boost::reg_expression是regex++库中的关键类,它表示“机器可读”的正则表达式,reg_expression 是在string的基础之上构建的,可以认为它是一个具有string的功能,外加这个正则表达式算法所需要的状态机。
像std::basic_string一样,它提供了两个针对char和wchar_t的特化版本:

namespace boost{
template <class charT,
          class traits = regex_traits<charT>,
          class Allocator = std::allocator<charT> >
class basic_regex;
typedef basic_regex<char> regex;
typedef basic_regex<wchar_t> wregex;
}

    要知道regex++库到底有什么用?可以试想我们要写一个信用卡处理程序。信用卡通常有16位数字组成的 号码,其中每四位一组,用空格或连字号隔开。在将这些信用卡号码存入数据库之前,我们难道不要检验这些数字是否符合正确格式么?为了匹配任何一个数字我们 可以用正则表达式[0-9],数字串的宽度可以用[[:digit:]],当然这些是POSIX标准。在regex++和perl中可简化为\d(注意许 多老的库倾向于硬编码到C-locale,因此这不是什么问题)。下面的正则表达式可以检验信用卡号码的格式。
(\d{4}[- ]){3}\d{4}
    ()标记子表达式,{4}表示重复4次。这仅是一个perl,awk,egrep的正则表达式的例子。regex++也支持那些sed,grep用到的比较老的“基本”语法,虽然它们很少用到,除非你需要重用一些已有的基本正则表达式。

    现在让我们把这个表达式置于C++代码中来检验信用卡号码的格式:

bool validate_card_format(const std::string s)
{
   static const boost::regex e("(
\\d{4}[- ]){3}\\d{4}");
   return regex_match(s, e);
}

    注意我们以前是如何将某些额外的转义序列(或者翻译成:转义字符)添加到表达式的:要知道,正则表达式引擎处理转义字符前,该转义字符只能被 C++编译器识别一次,因此,在C++代码中嵌入正则表达式的转义字符必须双写(写两次)。
    还要注意到你的编译器必须支持Koening lookup 2(比如VC6就不支持),否则你需要附加一些boost::prefixes到某些函数引用中。
    那 些熟悉信用卡操作的人,可能还会想到上面的那种格式适合于人的阅读,并不表示网上信用卡系统要求的格式(可能是16或15个没有间隔符的数字串)。我们需 要一种简单的转换方法,我们需要2个字符串,1个是正则表达式,一个是格式字符串(提供一种被匹配的内容的描述)。在regex++中,search和 replace都能完成regex_merge算法,对于信用卡的例子我们给出了下面2个算法用于格式转换:

// match any format with the regular expression:
const boost::regex e("
\\A(\\d{3,4})[- ]?(\\d{4})[- ]?(\\d{4})[- ]?(\\d{4})\\z");
const std::string machine_format("
\\1\\2\\3\\4");
const std::string human_format("
\\1-\\2-\\3-\\4");

std::string machine_readable_card_number(const std::string s)
{
   return regex_merge(s, e, machine_format, boost::match_default | boost::format_sed);
}

std::string human_readable_card_number(const std::string s)
{
   return regex_merge(s, e, human_format, boost::match_default | boost::format_sed);
}


    这儿,我们用正则表达式中的子式把号码分为4块,format string 用类似sed的语法把被匹配的内容替换为规定格式。
    上面的例子中,我们还没有直接操作匹配结果,匹配结果包括全体匹配和一些子式的匹配。当需要正则表达式的匹配结果时,就需要用到class match_results的实例,下面是常用类型的特化版本:

namespace boost{
typedef match_results<const char*> cmatch;
typedef match_results<const wchar_t*> wcmatch;
typedef match_results<std::string::const_iterator> smatch;
typedef match_results<std::wstring::const_iterator> wsmatch;
}

    regex_search和regex_grep算法都使用到match_result。
    注意这些算法并不局限于一般的C-strings,任何双向迭代器(bidirectional iterator)类型都能被搜索,这为无缝搜索任何类型数据提供了可能性。

    对于那些不喜欢模板(templates)的人还可以使用class RegEx,它是对模板代码的高层次包装,它为那些使用不到库的整个功能的人提供了简单的接口,当然它仅支持窄字符(narrow character)和“扩展”的正则表达式语法。
    对于想兼容POSIX的人可以使用POSIXAPI函数:regcomp,regexec,regfree,regerror,这些对narrow character和Unicode都适用。

    最后注意,这个库现在支持运行时本地化(run-time localization),它能完全识别POSIX正则表达式语法,包括一些多字符的元素比较和同等类型的高级特性,它还能兼容其它一些正则表达式库包括GNU、BSD4的regex包。

安装和配置

    首先当你从zip文件解压本库时必须保留它的内部结构,如果你没这样做,那只好删除你解压的文件,重现来一次。
    由于支持大多数常见的编译器/标准库/平台,这个库不需要作使用前的配置。如果你碰到配置问题,或想测试你的编译器的配置信息,可以参考 配置文档(这和boost的其它所有的库的处理过程都一样)。

    由于本库混合了模板代码(头文件中)和静态代码数据(cpp文件中),所以在你使用之前,必须将库支持的代码 生成到库内和档案文件中。以下是几个具体平台的操作步骤:
Borland C++ Builder

Microsoft Visual C++ 6 and 7
如果你使用VC5,你可能要找一下本库的以前版本。
打开命令提示符(其MSVC环境变量必须已定义,如果没有可运行Vcvars32.bat,位于<VC6>\bin),进入<boost>\libs\regex\build 目录
选择正确的makefile,VC6++的是vc6.mak,支持STLPort的是vc6-stlport.mak
如下调用
nmake -fvc6.mak
如果想在VC6子目录包含所有的lib、dll文件,lib文件拷在<VC6>\lib,dll文件拷在<VC6>\bin,可使用
nmake -fvc6.mak install
删除生成过程中所有的临时文件,可使用
nmake -fvc6.mak clean

最后只需添加<boost>根目录到你的工程所包含的目录列表中。没有必要手动将*.lib文件加到工程中,因为在头文件会选择正确的.lib文件。
注意:如果想静态地链入regex库,可定义BOOST_REGEX_STATIC_LINK(在release版中生效)。
      如果想直接使用源文件,可定义BOOST_REGEX_NO_LIB,这样自动选择库将失效。

1.简介出处:http://www.boost.org/libs/regex/doc/introduction.html
2.Koening lookup:When a function is called, in order to determine if that function is visible in the current scope, the namespaces in which the functions parameters reside must be taken into account.

 
 

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


posts - 94, comments - 138, trackbacks - 0, articles - 94

Copyright © RichardHe