From: http://blog.csdn.net/begtostudy/article/details/1879224
什么是正则表达式?正则表达式是一种用来描述一定数量文本的模式。Regex代表Regular Express。
如果您不知道什么是正则表达式,请看这篇文章http://blog.csdn.net/begtostudy/archive/2007/11/11/1879206.aspx
有了正则表达式的基础,问题是如何使用。我们以boost::regex来说
先看一个网上经典的例子。
#include "stdafx.h"
#include <cstdlib>
#include <stdlib.h>
#include <boost/regex.hpp>
#include <string>
#include <iostream>
using namespace std;
using namespace boost;
regex expression("^select ([a-zA-Z]*) from ([a-zA-Z]*)");
int main(int argc, char* argv[])
{
std::string in;
cmatch what;
cout << "enter test string" << endl;
getline(cin,in);
if(regex_match(in.c_str(), what, expression))
{
for(int i=0;i<what.size();i++)
cout<<"str :"<<what[i].str()<<endl;
}
else
{
cout<<"Error Input"<<endl;
}
return 0;
}
==============
结果
输入:select name from table
输出:str:select name from table
str:name
str:table
按照我们的要求,字符串被匹配挑出来了。
这在处理大量规则的文本格式的时候很有用,因为它很灵活,一通百通。
首先,即使你拥有了boost库,也需要单独编译regex。
如果你不知道boost库,看这里http://www.stlchina.org/twiki/bin/view.pl/Main/BoostStartIntroduce
网上的介绍:
boost库安装比较麻烦,需要自己编译源文件,我整理了一下,如果仅仅需要做正则表达式,按下面的代码敲就行了:
cmd
vcvars32.bat
cd D:/boost_1_32_0/libs/regex/build
d:
nmake -fvc6.mak
nmake -fvc6.mak install
注意,别看下载下来的数据包没有多大,解压缩之后达到了100多M,编译完之后为109M,占用131M,所以安装时一定注意空出足够的空间,敲入nmake -fvc6.mak后等待的时间比较长,屏幕上还会出现一大堆英语,可以不做考虑。按照步骤往下敲就行了。压缩包内文档很详细,参照文档继续就可以了。
在VC6中集成:Tools->Options->Directories->Include files
加入:D:/boost_1_32_0
我用的是VS2003
做了run.bat
chdir E:/Program/boost_1_34_1
bjam "-sTOOLS=vc-7_1" "-sVC71_ROOT=D:/Program Files/Microsoft Visual Studio .NET 2003/Vc7" "--prefix=E:/Program/boost" "--builddir=E:/Program/boost_1_34_1/build" "-sBUILD=debug release <runtime-link>static/dynamic" --with-regex install
PAUSE
至于参数,需要参考boost安装介绍http://blog.csdn.net/begtostudy/archive/2007/11/11/1879213.aspx
其他的一些介绍
bool validate_card_format(const std::string s)
{
static const boost::regex e("(//d{4}[- ]){3}//d{4}");
return regex_match(s, e);
}
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正则表达式语法可参见《perl语言入门》第7、8、9章或boost的文档。这里列出的语法是不全面的,而且部分说明可能并不清楚。
. 任意字符;使用match_no_dot_null标志时不匹配NULL字符; 使用match_not_dot_newline时不匹配换行字符
^ 匹配行的开始
$ 匹配行的结束
* 重复零次或则更多,例如a*b可匹配b,ab,aab,aaaaaaab
+ 重复一次以上,例如a+b可匹配ab,aab,aaaaaaaab。但不能匹配b了
? 零次或则一次,例如ca?b匹配cb,cab但不匹被caab
a{n} 匹配字符'a'重复n次
a{n,},字符a重复n次以上(含n次)
a{n,m} a重复n到m次(含)
*? 匹配前一个原子零次以上
+? 匹配前一个原子一次以上
?? 匹配前一个原子零次以上
{n,}? 匹配前一个原子n次以上(含)
{n,m? 匹配前一个原子n到m次(含)
| 或操作,例如ab(d|ef)匹配abd或则abef
[] 字符集操作,例如[abc]将匹配任何单个字符'a','b','c'
[a-d],表示a、b、c、d
^否操作,例如[^a-c]表示a至c之外的所有字符
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);
模板类:
l basic_regex 用来保存一个“正则表达式”的类。
l sub_match 继承于pair<Iterator,Iterator>迭代器组,用来表示匹配的一个结果。
l match_results sub_match的容器,用来表示一次搜索或匹配算法的所有结果,类似于vector<sub_match>。
算法:
l regex_math 匹配算法,测试一个字符串是否和一个正则式匹配,并通过match_results返回结果。
l regex_find 查找算法,查找字符串的一个和正则式匹配的字串,并通过match_results返回结果。
l regex_format 替换算法,查找字符串中的所有匹配正则式的字串,并使用“格式化字符”串替换。
迭代器:
l regex_iterator 枚举一个字符串中所有匹配的字串,regex_iterator的结果相当于match_results。
l regex_token_iterator 枚举一个字符串中所有匹配的字串,regex_iterator的结果相当于sub_match。
详述
l basic_regex
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;
很明显,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<char>(cout));
其他:
re.size() | 正则表达式长度,即str的长度。 |
re.max_size() | 正则表达式的最大长度。 |
re.empty() | 长度是否为0 |
re.mark_count() | 返回正则式的组数,一般情况下为小括号对数+1。在boost.regex中使用小括号分组,详情请看下面的算法详解。 |
re.flags() | 返回语法选项。 |
cout<<re | 正则式的流输出,相当于上面示例的copy算法。 |
swap | 成员函数,全局函数都有 |
re.imbue(loc) | 设置local为loc,返回原来的local |
re.getloc() | 得到当前local |
==,!=,<,<=,>,>= | 比较运算符重载 |
l sub_match
sub_match是一个迭代器组,表示正则式中的一个匹配。
template <class BidirectionalIterator>
class sub_match : public std::pair<BidirectionalIterator, BidirectionalIterator>;
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转换。 |
还有就是一大堆的比较操作符的重载了,这里就不多说了。
l match_results
match_results相当于sub_match的容器,用于表示正则式算法的返回结果。
template <class BidirectionalIterator,
class Allocator = allocator<sub_match<BidirectionalIterator> >
class match_results;
typedef match_results<const char*> cmatch;
typedef match_results<const wchar_t*> wcmatch;
typedef match_results<string::const_iterator> smatch;
typedef match_results<wstring::const_iterator> wsmatch;
声明很简单,有四个特化可以直接使用,不过要注意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 | 流输出,输出整个匹配,相当于cout<<m[0]。因为第0个元素是整个匹配,详细情况请看下面的解释。 |
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.]+)$");
大家看看还有没有更好的写法?