分类: C/C++
2010-11-02 17:23:46
Boost.Regex手里有七种武器和两大法宝
其中的七种武器是:
regex_match 函数
regex_search 函数
regex_replace 函数
regex_format 函数
regex_grep 函数
regex_split 函数
RegEx 类
每种武器都又有诸多变化(每个函数都分别以C字符串类型、std::string类型、迭代器类型作为参数重载),不过后面四种武器因年久失修已不建议使用.
两大法宝是:
regex_iterator 迭代器
regex_token_iterator 迭代器
这两大法宝是整个Boost.Regex的灵魂,用熟它们以后那是“摘花飞叶即可伤人”啊~~
boost::regex的默认正则表达式语法是perl语法
boost::regex支持perl regular表达式、POSIX-Extended regular表达式和POSIX-Basic Regular表达式,但默认的表达式语法是perl语法,如果要使用其余两种语法需要在构造表达式的时候明确指定。
例如,下面两种方法效果相同
// e1 is a case sensitive Perl regular expression:
// since Perl is the default option there''s no need to explicitly specify the syntax used here:
boost::regex e1(my_expression);
// e2 a case insensitive Perl regular expression:
boost::regex e2(my_expression, boost::regex::perl|boost::regex::icase);
perl正则表达式语法可参见《perl语言入门》第7、8、9章或boost的文档
boost::regex对unicode编码的支持
boost::regex使用ICU来实现对unicode及unicode变种的支持,这需要在编译boost的时候指出是否使用ICU以及ICU所在的目录。否则编译出来的boost::regex不支持unicode编码。其中boost::wregex支持unicode编码的搜索,如果要搜索UTF-8、UTF-16、UFT-32编码的字符串,则要用boost::u32regex。注意boost::wregex只能支持unicode编码,不能支持uft编码。
搜索时如何忽略大小写
如果要在搜索时忽略大小写(即大小写不敏感),则要用到表达式选项boost::regex::icase,例如: boost::regex e2(my_expression, boost::regex::perl|boost::regex::icase);
模板类:
basic_regex 用来保存一个“正则表达式”的类。
sub_match 继承于pair
match_results sub_match的容器,用来表示一次搜索或匹配算法的所有结果,类似于vector
算法:
regex_match 匹配算法,判断一个正则表达式(参数 e)是否匹配整个字符序列 str.
它主要用于验证文本。注意,这个正则表达式必须匹配被分析串的全部,否则函数返回 false.
如果整个序列被成功匹配,regex_match 返回 True.
regex_search 查找算法,类似于 regex_match, 但它不要求整个字符序列完全匹配。你可以用 regex_search
来查找输入中的一个子序列,该子序列匹配正则表达式 e.
regex_replace 替换算法,在整个字符序列中查找正则表达式e的所有匹配。这个算法每次成功匹配后,就根据参数fmt对匹配字符串进行格式化。缺省情况下,不匹配的文本不会被修改,即文本会被输出但没有改变。
迭代器:
regex_iterator 枚举一个字符串中所有匹配的字串,regex_iterator的结果相当于match_results。
regex_token_iterator 枚举一个字符串中所有匹配的字串,regex_iterator的结果相当于sub_match。
详述
basic_regex
template
class basic_regex;
typedef basic_regex
typedef basic_regex
很明显,charT是正则式的字符类型,regex和wregex是basic_regex的两个特化。
注意,正则式的字符类型要和需要匹配的字符串的字符类型相同。例如:不能在regex_find算法中分别使用string和wregex最为参数,要么是string和regex,要么是wstring和wregex。
构造函数:
basic_regex re
产生空的正则式
basic_regex re(str)
正则式为str,str可以为basic_string,也可以是0结尾的char*字符串。
Basic_regex re(re2)
拷贝构造。
basic_regex re(str,flag)
正则式为str,使用flag语法选项,flag是一组常量的组合。例如:icase可以使正则式匹配忽略大小写。
basic_regex re(beg,end)
使用迭代器构造正则式。可以是basic_string的迭代器,也可以是const char*。
basic_regex re(beg,end,flag)
使用迭代器构造正则式,flag是语法选项。
常用的语法选项:
regex_constants::normal
默认的语法。符合EMCAScript,JavaScript中的正则式。
regex_constants::icase
匹配的时候忽略大小写。
regex_constants::nosubs
不把匹配的子串保存进match_results结构。
regex_constants::collate
对于[a-b]的匹配,考虑地区
语法选项通过或运算来结合。在basic_regex中这些语法选项也进行了定义,所以可以写成regex::normal,这要比regex_constants少打好几个字母了吧!J
assign成员函数:
re.assign(re2)
复制一个正则式
re.assign(str)
正则式为str。
re.assign(str, flag)
正则式为str,使用flag语法选项,flag是一组常量的组合。
re.assign(beg, end)
使用迭代器构造正则式。
re.assign(beg, end, flag)
使用迭代器构造正则式,flag是语法选项。
其实basic_regex很多用法和basic_string很像,因为正则表达式也是个字符串嘛!
迭代器:
regex::iterator it
常迭代器类型,即const_iterator
re.begin()
返回的是常迭代器哦!const_iterator
re.end()
没有逆向迭代器。
例如:copy(re.begin(), re.end(), ostream_iterator
其他:
re.size()
正则表达式长度,即str的长度。
re.max_size()
正则表达式的最大长度。
re.empty()
长度是否为0
re.mark_count()
返回正则式的组数,一般情况下为小括号对数+1。在boost.regex中使用小括号分组,详情请看下面的算法详解。
re.flags()
返回语法选项。
cout<
swap
成员函数,全局函数都有
re.imbue(loc)
设置local为loc,返回原来的local
re.getloc()
得到当前local
==,!=,<,<=,>,>=
比较运算符重载
sub_match
sub_match是一个迭代器组,表示正则式中的一个匹配。
template
class sub_match : public std::pair
boost没有提供sub_match的任何特化,因为我们不会显示的声明一个sub_match变量。sub_match是作为match_results的元素用的。比如:match_results的operator[]和迭代器返回的就是一个特化的sub_match。
唯一的成员变量:
bool matched 是否匹配。
成员函数:
length()
返回长度,即两个迭代器之间的距离。
operator basic_string< value_type>()
隐式的basic_string转换。
str()
显式的basic_string转换。
还有就是一大堆的比较操作符的重载了,这里就不多说了。
match_results
match_results相当于sub_match的容器,用于表示正则式算法的返回结果。
template
class Allocator = allocator
class match_results;
typedef match_results
typedef match_results
typedef match_results
typedef match_results
声明很简单,有四个特化可以直接使用,不过要注意string和char*字符串使用的match_results是不同的。
成员函数:
m.size()
容量。
m.max_size()
最大容量。
m.empty()
容量是否为0。
m[n]
第n个元素,即sub_match
m.prefix()
返回代表前缀的sub_match,前缀指字符串的开头到第一个匹配的开头。
m.suffix()
返回代表后缀的sub_match,后缀之最后一个匹配的结尾到字符串的结尾。
m.length(n)
返回第n个元素的长度,即m[n].size()。
m.position(n)
返回第n个元素的位置。
cout<
m.format(fmtstr)
使用格式化字符串,格式化结果,返回字符串
m.format(fmtstr,flags)
使用格式化字符串,格式化结果,返回字符串,flags是格式化选项。
m.format(out,fmtstr)
同上,但是使用输出迭代器输出结果。
m.format(out.fmtstr,flags)
同上,但是使用输出迭代器输出结果。
迭代器:
smatch::iterator
迭代器,常迭代器
smatch::const_iterator
同上
m.begin()
返回常迭代器
m.end()
同上
最后,说一个实例
我处理一个文本
实际值/-20.031,-1.896,-2.861,-1,0,0
提取其中的数字
regex exp("\s*实际值/(-?[0-9.]+),(-?[0-9.]+),(-?[0-9.]+),(-?[0-9.]+),(-?[0-9.]+),(-?[0-9.]+)$");
大家看看还有没有更好的写法?
regex_match
regex_match算法用来测试一个字符串是否完全匹配正则式。让我们来看一下regex_match的使用:
if (regex_match(str, m, re))
{
...
}
str是一个字符串,可以是string,wstring,char *或者wchar_t *
m是match_results,它通过引用传入参数,来保存匹配的结果,m要和str的类型匹配,可以是smatch,wsmatch,cmatch或wcmatch,用来分别对应string,wstring,char *或者wchar_t*的str。
re就是正则表达式了,一般来说是regex或wregex。
str,m,re的类型如下:
str类型 | m类型 | re类型 |
string | smatch (match_results | regex (basic_regex |
wstring | wsmatch (match_results | wregex (basic_regex |
char* | cmatch (match_results | regex (basic_regex |
wchar_t* | wcmatch (match_results | wregex (basic_regex |
函数的返回值表示字符串是否完全匹配正则表达式,当返回true的时候,m保存了匹配的结果;返回false,m未定义。
下面让我们来看一下,当函数返回true的时候,m是怎么样的。
m.size() == re.mark_count()
还记得re.mark_count()返回的是什么吗?在上一篇中说的是re.mark_count()返回的时正则式的“组数”,并没有详细解释。这里我要详细解释一下。
其实,这个“组数”在boost的regex中叫做sub-expression。sub-expression就是在正则式中使用小括号括起来的一部分,正则式本身是一个sub-expression,所以re.mark_count()等于小括号对数+1。
m.prefix()和m.suffix()
这两个返回的是sub_match类型(相当于一个迭代器组)。在regex_match算法中,这两个返回的sub_match都是空的,他们的值如下:(sub_match继承于pair,所以有first和second成员哦)
m.prefix().first == str.begin()
m.prefix().second == str.begin()
m.prefix().matched == false
m.suffix().first == str.end()
m.suffix().second == str.end()
m.suffix().matched == false
因为regex_match是完全匹配,即整个字符串和正则式匹配,所以前缀和后缀都是空的。
m[0]
返回第0个匹配的,由于regex_match是完全匹配,所以
m[0].first == str.begin()
m[0].second == str.end()
m[0].matched == true
m[n] , n
返回第n个匹配的sub-expression。
m[n].matched 表示第n个sub-expression是否在字符串中存在。整个regex匹配,但是sub_exp可能匹配的是空的,例如”(a*)”就有可以匹配空。
m[n].first和m[n].second 表示匹配的范围。如果匹配空的话,都为str.end()。
根据我的测试,m[1],m[2],...,m[n]的顺序是按照正则式的左小括号的顺序来的,例如对于正则式”((a)bc)d(efg)”,如果匹配了一个字符串的话(字符串只可能是”abcdefg”),则
m[0] == “abcdefg” (sub_match重载了==运算符使得可以和一个字符串比较)
m[1] == “abc”
m[2] == “a”
m[3] == “efg”
regex_match的其它用法
regex_match(str,re) | 只测试是否匹配,不需要匹配的结果 |
regex_match(beg,end,re) | 输入的是迭代器 |
regex_match(beg,end,m,re) | 注意m的类型为match_results |
regex_match(str,m,re,flag) | flag是匹配选项,默认是的regex_constants::match_default |
regex_search
regex_search的用法基本上和regex_match一样。
if (regex_search(str, m, re))
{
...
}
regex_search不要求str完全匹配re,只要str中的一个字串匹配re就可以了。所以,m.prefix()和m.suffix()不一定为空。
regex_search是从左往右匹配,而且尽量匹配长的字串。
2.示例代码
先准备一个测试用的数据备用,如果各位有雅兴可以参考本站的另一篇文章《》使用Google Testing框架来做这个实验,花一样时间学两样啊~~
|
要确定一行字符串是否与指定的正则表达式匹配,使用regex_match。
下面这个代码可以验证szStr字串(定义在上面)是否与szReg匹配。
|
|
|
typedef match_results cmatch;
typedef match_results smatch;
typedef match_results wcmatch;
typedef match_results wsmatch;
可以把match_results看成是一个sub_match的容器,同时它还提供了format方法来代替regex_format函数。
一个sub_match就是一个子串,它从std::pair
regex_match只验证是否完全匹配,如果想从一大串字符串里找出匹配的一小段字符串(比如从网页文件里找超链接),这时就要使用regex_search了。
下面这段代码从szStr中找数字
|
|
|
对应于C字符串和C++字符串以及宽字符,regex_iterator同样也有四个特化:
typedef regex_iterator cregex_iterator;
typedef regex_iterator sregex_iterator;
typedef regex_iterator wcregex_iterator;
typedef regex_iterator wsregex_iterator;
这个迭代器的value_type定义是一个match_results。
|
Boost.Regex也提供了make_regex_iterator函数简化regex_iterator的构造,如上面的itrBegin可以写成:
itrBegin = make_regex_iterator(szStr,reg);
它同样也有四个特化,形式和上面类似,就不再写一遍骗篇幅了。这个迭代器的value_type定义是一个sub_match。
|
|
|
chinaunix网友2010-11-03 16:16:30
很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com