Boost::regex 应用举例(一)
newsuppy April, 2010
一, 安装 Boost 程序库
Boost 为 C++ 提供了大量十分有用但是还未被加入到标准库中的程序库,我们可以从 www.boost.org 获取程序库的源代码。 Boost 中的某些库只需要 include 头文件就可以使用,另外一些则需要先行编译,如 regex 正则表达式就是一例。如何安装编译 Boost? 这里仅介绍一下在 Windows 平台,如果已经安装了 Visual C++ 9 编译器,只需要将 Boost 包解压缩后,运行根目录中的 bootstrap.bat 先行生成 bjam.exe 程序( Boost 的 Make 系统),然后运行 bjam.exe 后,就开始编译 Boost ,完成后会生成 boost.v2 和 stage 目录,内有编译后的 lib 文件。接下来,我们就可以开始用 boost::regex 库了,另外 regex 也存在于 C++ TR1 ( Technical Report, 即下一个 C++0x 标准,也许该是 C++1x 了)中,下文介绍仍旧以 boost::regex 为准。编译时时需要链接相应的 lib 文件。
二, 文本匹配示例
需要处理的文件格式是这样的:文件中存在大量 name =”value ” 格式,这种格式在一行中可能存在一个,也可能是多个,其中带有下划线的斜体字为变量,需要提取出这种格式,存入到一个数据库的某个 name-value 的表中。如表 2-1 所示为示例文件的格式
NAME=”REGEX” TYPE=”C++ Class” DESCRIPTION=”Boost C++ Class” ATTRIBUTE_MEMBER_1 = “regex string” FUNCTION_MEMBER_1 = ”search” |
表 2-1 |
首先是构建一个可以匹配 name =”value ” 格式的正则表达式,注意 name 只包含单词,字母,数字以及下划线的组合,正好与正则表达式的 ’/w’ 匹配,另外 ’=’ 的前后可以有空白字符(空格或 Tab ); ”value ” 是以双引号括起来的文本, value 本省不可以有双引号字符,那么用 "[^"]*" 来匹配,即由双引号括起来,但是不包含双引号本身的所有字符,如果只已 "*" 来表示,那么就正能匹配单个 name =”value ” ,遇到多个就会有问题。
在 boost::regex 中就构建这样一个正则表达式:
boost::regex reg("(//w+)[//s]*=[//s]*/"([^/"]*)/"");
注意 C++ 中的 ’/’ 为转义符,所有需要 ’//’ 来表示 ’/’ 。表达式中的 ’( )’ 是为了提取 name 和 ”value ” 的,否则只能得到整个的匹配的文本。
整个的代码片段就如表 2-2 :
string full_file_name = path_name_ + dbsrc_file_name_; ifstream src_file(full_file_name.c_str()); string current_line; int line_num = 0; ofstream match_info_file("match_info.src" ); if (src_file) { while (!src_file.eof()) { std::getline(src_file, current_line); ++line_num; boost::regex reg("(//w+)[//s]*=[//s]*/"([^/"]*)/"" ); boost::smatch src_macth_results;
std::string::const_iterator it=current_line.begin(); std::string::const_iterator end=current_line.end(); match_info_file << "line num: " << line_num << "/t" ; bool match_flag = false ; for (;it!=end;) { if ((match_flag = boost::regex_search(it, end, src_macth_results, reg))) { for (int m_id=0; m_id<src_macth_results.size(); ++m_id) { if (src_macth_results[m_id].matched) { match_info_file << "match id(matched): " << m_id << "/t" << "match string: " << src_macth_results[m_id].str() << "/n" ; } } it = src_macth_results.suffix().first; } else { ++it; } } if (match_flag == false && current_line.length() >=1) match_info_file << "not match line: " << line_num << "/t" << current_line.c_str() << "/n" ; else if (match_flag == false && current_line.length() <1) match_info_file << "not match line: " << line_num << "/t" << "Blank Line" << "/n" ;; } match_info_file.flush(); match_info_file.close(); } src_file.close(); |
表 2-1 |
因为单行文本中的 name =”value ” 格式可能有多个,所以在匹配时需要用 boost::regex_search ,而 boost::regex_match 是用于完全匹配的,如果用在这里就无法匹配单行中的多个 name =”value ” 格式了。匹配的结果可以在 match_results 中提取出来,其中 match_results 的第 0 个是整个匹配的字符串,而其余的则是用 ’( )’ 括起来的被提取部分,对于上面的示例来说就是 name 对应于 match_results 第 1 个结果, ”value ” 对应于 match_results 第 2 个结果。
三, 推荐书籍
以上内容就是一些简要的介绍,所以再推荐一些书目。
1, Boost 本身的 regex 文档就是很好的参考;
2, Beyond the C++ Standard Library: An Introduction to Boost , By Björn Karlsso, 2005 年的老书了,对于 boost 的简单介绍,当然包括 regex 。
3, Mastering Regular Expressions, 3rd Edition , By Jeffrey E. F. Friedl ,国内也有本书的中译本,余晟 译。几乎是正则表达式的最佳书籍了,介绍了各种正则表达式的方言,当然 boost::regex 也支持多种方言的正则表达式。
4, The C++ Standard Library Extensions: A Tutorial and Reference, By Pete Becker, 主要是围绕 C++ TR1 的内容,也包含 regex ,国内有中译本,史晓明 译。