来源:http://blog.chinaunix.net/uid-21222282-id-1829265.html
来源:http://www.cnblogs.com/undermoon/archive/2009/11/30/1613508.html
来源:http://blog.csdn.net/guyulongcs/article/details/7838753
来源:http://blog.csdn.net/leonardwang/article/details/6035171
boost::regex类为C++提供了完整的正则表达式支持,并且已被接收为C++0x标准库。它同时也在Boost库中扮演着极重要的角色,不少Boost子库都需要它的支持,有不少人甚至就是为了它才下载使用Boost的。
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);
boost::regex对unicode编码的支持
(2)match_results
match_results是用来表示所有匹配指定正则表达式的字符串的集合的对象类型。Boost.Regex提供了四种标准类型的定义:C单字节字符类型的cmatch, C宽字符类型的wcmatch, C++单字节字符类型smatch, C++宽字符类型wsmatch。match_results所提供的接口参见:
http://www.boost.org/doc/libs/1_37_0/libs/regex/doc/html/boost_regex/ref/match_results.html
(3)sub_match
sub_match是用来表示匹配指定正则表达式的字符串的对象类型。match_results就是由sub_match组成的集合类型。
关于sub_match类型,有下面三点需要注意的:
a. sub_match类型的对象只能通过对match_results类型的对象取下标获取
b. sub_match类型的对象可以和std:basic_string或const char*的字符串进行比较
c. sub_match类型的对象可以和std::basic_string或const char*的字符串相加,生成新的std::basic_string类型的字符串
sub_match所提供的接口请参考:
http://www.boost.org/doc/libs/1_37_0/libs/regex/doc/html/boost_regex/ref/sub_match.html
(4)reg_match, reg_search和reg_replace
reg_match, reg_search和reg_replace都是Boost.Regex所提供的具体进行正则匹配的算法接口。
reg_match用来判定整个字符串是否匹配指定的的正则表达式, 具体定义参见:
http://www.boost.org/doc/libs/1_37_0/libs/regex/doc/html/boost_regex/ref/regex_match.html
reg_search用来判定字符串的某一部分是否匹配指定的正则表达式, 具体定义参见:
http://www.boost.org/doc/libs/1_37_0/libs/regex/doc/html/boost_regex/ref/regex_search.html
reg_replace用来把字符串中匹配指定正则表达式的部分替换为指定内容输出,对于不匹配的部分原样输出, 具体定义参见:
http://www.boost.org/doc/libs/1_37_0/libs/regex/doc/html/boost_regex/ref/regex_replace.html
#include
#include
#include "boost/regex.hpp"
int main(int argc, char ** argv)
{
if (argc != 4)
{
std::cerr<<"Usage: " << argv[0] <<" option regex text\n"
<<" option: 0 --whole match\n"
<<" 1 --sub match\n"
<<" 2 --replace match\n";
return 1;
}
boost::regex oRegex(argv[2]);
boost::smatch oResults;
std::string strStr(argv[3]);
std::string strRes;
switch (atoi(argv[1]))
{
case 0:
if(boost::regex_match(strStr, oResults, oRegex))
{
std::cout << strStr << " matches " << oRegex << "\n";
}
else
{
std::cout << strStr << " doesn't match " << oRegex << "\n";
}
break;
case 1:
if(boost::regex_search(strStr, oResults, oRegex))
{
std::cout << strStr << " matches " << oRegex << "\n";
}
else
{
std::cout << strStr << " doesn't match " << oRegex << "\n";
}
break;
case 2:
strRes = boost::regex_replace(strStr, oRegex, "");
std::cout << "strRes=" << strRes << "\n";
break;
default:
std::cerr << "Invalid option: " << argv[1] << "\n";
break;
}
}
要使用Boost.Regex, 你需要包含头文件"boost/regex.hpp". Regex是本书中两个需要独立编译的库之一(另一个是Boost.Signals)。你会很高兴获知如果你已经构建了Boost— —那只需在命令提示符下打一行命令——就可以自动链接了(对于Windows下的编译器),所以你不需要为指出那些库文件要用而费心。
你要做的第一件事就是声明一个类型 basic_regex 的变量。这是该库的核心类之一,也是存放正则表达式的地方。创建这样一个变量很简单;只要将一个含有你要用的正则表达式的字符串传递给构造函数就行了。
boost::regex reg("(A.*)");
模板类:
l basic_regex 用来保存一个“正则表达式”的类。
l sub_match 继承于pair
l match_results sub_match的容器,用来表示一次搜索或匹配算法的所有结果,类似于vector
算法:
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。
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的灵魂,用熟它们以后那是“摘花飞叶即可伤人”啊~~
所需头文件 #include
示例代码 :先准备一个测试用的数据备用,如果各位有雅兴可以参考本站的另一篇文章《Google Testing》使用Google Testing框架来做这个实验,花一样时间学两样啊~~
#include
#include
using namespace std;
int main(int argc, char* argv[])
{
//( 1 ) (( 3 ) 2 )(( 5 )4)( 6 )
//(\w+)://((\w+\.)*\w+)((/\w*)*)(/\w+\.\w+)?
//^协议://网址(x.x...x)/路径(n个\字串)/网页文件(xxx.xxx)
const char *szReg = "(\\w+)://((\\w+\\.)*\\w+)((/\\w*)*)(/\\w+\\.\\w+)?";
const char *szStr = "http://www.cppprog.com/2009/0112/48.html";
//练习代码...
cin.get(); //暂停
}
{ //字符串匹配
boost::regex reg( szReg );
bool r=boost::regex_match( szStr , reg);
assert(r); //是否匹配
}
boost::regex的构造函数中还可以加入标记参数用于指定它的行为,如:
//指定使用perl语法(默认),忽略大小写。
boost::regex reg1( szReg, boost::regex::perl|boost::regex::icase );
//指定使用POSIX扩展语法(其实也差不多)
boost::regex reg2( szReg, boost::regex::extended );
下面这个代码不仅验证是否匹配,而且可以从中提取出正则表达式括号对应的子串。
{ //提取子串
boost::cmatch mat;
boost::regex reg( szStr );
bool r=boost::regex_match( szStr, mat, reg);
if(r) //如果匹配成功
{
//显示所有子串
for(boost::cmatch::iterator itr=mat.begin(); itr!=mat.end(); ++itr)
{
// 指向子串对应首位置 指向子串对应尾位置 子串内容
cout << itr->first-szStr << ' ' << itr->second-szStr << ' ' << *itr << endl;
}
}
//也可直接取指定位置信息
if(mat[4].matched) cout << "Path is" << mat[4] << endl;
}
其中,boost::cmatch是一个针对C字符串的特化版本,它还有另三位兄弟,如下:
typedef match_results cmatch;
typedef match_results smatch;
typedef match_results wcmatch;
typedef match_results wsmatch;
可以把match_results看成是一个sub_match的容器,同时它还提供了format方法来代替regex_format函数。 { //查找
boost::cmatch mat;
boost::regex reg( "\\d+" ); //查找字符串里的数字
if(boost::regex_search(szStr, mat, reg))
{
cout << "searched:" << mat[0] << endl;
}
}
{ //替换1,把上面的HTTP的URL转成FTP的
boost::regex reg( szReg );
string s = boost::regex_replace( string(szStr), reg, "ftp://$2$5");
cout << "ftp site:"<< s << endl;
}
正则表达式中,使用(?1~?9新字串)表示把第几个子串替换成新字串
{ //替换2,使用format_all参数把<>&全部转换成网页字符
string s1 = "(<)|(>)|(&)";
string s2 = "(?1<)(?2>)(?3&)";
boost::regex reg( s1 );
string s = boost::regex_replace( string("cout << a&b << endl;"), reg, s2, boost::match_default | boost::format_all);
cout << "HTML:"<< s << endl;
}
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 reg( "\\d+" ); //查找字符串里的数字
boost::cregex_iterator itrBegin(szStr, szStr+strlen(szStr), reg);
boost::cregex_iterator itrEnd;
for(boost::cregex_iterator itr=itrBegin; itr!=itrEnd; ++itr)
{
// 指向子串对应首位置 指向子串对应尾位置 子串内容
cout << (*itr)[0].first-szStr << ' ' << (*itr)[0].second-szStr << ' ' << *itr << endl;
}
}
Boost.Regex也提供了make_regex_iterator函数简化regex_iterator的构造,如上面的itrBegin可以写成:itrBegin = make_regex_iterator(szStr,reg);
{ //使用迭代器拆分字符串
boost::regex reg("/"); //按/符拆分字符串
boost::cregex_token_iterator itrBegin(szStr, szStr+strlen(szStr), reg,-1);
boost::cregex_token_iterator itrEnd;
for(boost::cregex_token_iterator itr=itrBegin; itr!=itrEnd; ++itr)
{
cout << *itr << endl;
}
}
Boost.Regex也提供了make_regex_token_iterator函数简化regex_token_iterator的构造,最后的那个参数-1表示以reg为分隔标志拆分字符串,如果不是-1则表示取第几个子串,并且可以使用数组来表示同时要取几个子串,例如:
{ //使用迭代器拆分字符串2
boost::regex reg("(.)/(.)"); //取/的前一字符和后一字符(这个字符串形象貌似有点邪恶-_-)
int subs[] = {1,2}; // 第一子串和第二子串
boost::cregex_token_iterator itrBegin = make_regex_token_iterator(szStr,reg,subs); //使用-1参数时拆分,使用其它数字时表示取第几个子串,可使用数组取多个串
boost::cregex_token_iterator itrEnd;
for(boost::cregex_token_iterator itr=itrBegin; itr!=itrEnd; ++itr)
{
cout << *itr << endl;
}
}
#include
#include
using namespace std;
int main(int argc, char* argv[])
{
//( 1 ) (( 3 ) 2 )(( 5 )4)( 6 )
//(\w+)://((\w+\.)*\w+)((/\w*)*)(/\w+\.\w+)?
//^协议://网址(x.x...x)/路径(n个\字串)/网页文件(xxx.xxx)
const char *szReg = "(\\w+)://((\\w+\\.)*\\w+)((/\\w*)*)(/\\w+\\.\\w+)?";
const char *szStr = "http://www.cppprog.com/2009/0112/48.html";
{ //字符串匹配
boost::regex reg( szReg );
bool r=boost::regex_match( szStr , reg);
assert(r);
}
{ //提取子串
boost::cmatch mat;
boost::regex reg( szReg );
bool r=boost::regex_match( szStr, mat, reg);
if(r) //如果匹配成功
{
//显示所有子串
for(boost::cmatch::iterator itr=mat.begin(); itr!=mat.end(); ++itr)
{
// 指向子串对应首位置 指向子串对应尾位置 子串内容
cout << itr->first-szStr << ' ' << itr->second-szStr << ' ' << *itr << endl;
}
}
//也可直接取指定位置信息
if(mat[4].matched) cout << "Path is" << mat[4] << endl;
}
{ //查找
boost::cmatch mat;
boost::regex reg( "\\d+" ); //查找字符串里的数字
if(boost::regex_search(szStr, mat, reg))
{
cout << "searched:" << mat[0] << endl;
}
}
{ //替换
boost::regex reg( szReg );
string s = boost::regex_replace( string(szStr), reg, "ftp://$2$5");
cout << "ftp site:"<< s << endl;
}
{ //替换2,把<>&转换成网页字符
string s1 = "(<)|(>)|(&)";
string s2 = "(?1<)(?2>)(?3&)";
boost::regex reg( s1 );
string s = boost::regex_replace( string("cout << a&b << endl;"), reg, s2, boost::match_default | boost::format_all);
cout << "HTML:"<< s << endl;
}
{ //使用迭代器找出所有数字
boost::regex reg( "\\d+" ); //查找字符串里的数字
boost::cregex_iterator itrBegin = make_regex_iterator(szStr,reg); //(szStr, szStr+strlen(szStr), reg);
boost::cregex_iterator itrEnd;
for(boost::cregex_iterator itr=itrBegin; itr!=itrEnd; ++itr)
{
// 指向子串对应首位置 指向子串对应尾位置 子串内容
cout << (*itr)[0].first-szStr << ' ' << (*itr)[0].second-szStr << ' ' << *itr << endl;
}
}
{ //使用迭代器拆分字符串
boost::regex reg("/"); //按/符拆分字符串
boost::cregex_token_iterator itrBegin = make_regex_token_iterator(szStr,reg,-1); //使用-1参数时拆分,使用其它数字时表示取第几个子串,可使用数组取多个串
boost::cregex_token_iterator itrEnd;
for(boost::cregex_token_iterator itr=itrBegin; itr!=itrEnd; ++itr)
{
cout << *itr << endl;
}
}
{ //使用迭代器拆分字符串2
boost::regex reg("(.)/(.)"); //取/的前一字符和后一字符(这个字符串形象貌似有点邪恶-_-)
int subs[] = {1,2}; // 第一子串和第二子串
boost::cregex_token_iterator itrBegin = make_regex_token_iterator(szStr,reg,subs); //使用-1参数时拆分,使用其它数字时表示取第几个子串,可使用数组取多个串
boost::cregex_token_iterator itrEnd;
for(boost::cregex_token_iterator itr=itrBegin; itr!=itrEnd; ++itr)
{
cout << *itr << endl;
}
}
cin.get();
return 0;
}
std::string str("abcd");
boost::regex reg( "a\\w*d" );
if (regex_match(str, reg))
{
std::cout << str << " is match" << std::endl;
}
else
{
std::cout << str << " is not match" << std::endl;
}
2、完全匹配并获取子串
const char* mail = "[email protected]";
boost::cmatch res;
//建立3个子表达式
boost::regex reg("(\\w+)@(\\w+).(\\w+)");
if (boost::regex_match(mail,res, reg))
{
//既可以通过迭代器获取数据, 也可以通过数组方式获取数据
for (boost::cmatch::iterator pos = res.begin(); pos != res.end(); ++pos)
{
std::cout << *pos << std::endl;
}
//res[0]存放匹配到的完整字符串
std::cout << "name:" << res[1] << std::endl;
}
3、查找, 当你不需要匹配整个字符串的时候,可以选择查找
const char* mail = "[email protected]";
boost::cmatch res;
//建立3个子表达式
boost::regex reg("(\\w+)@(\\w+).(\\w+)");
if (boost::regex_search(mail,res, reg))
{
std::cout <<"**************************************" << std::endl;
//既可以通过迭代器获取数据, 也可以通过数组方式获取数据
for (boost::cmatch::iterator pos = res.begin(); pos != res.end(); ++pos)
{
std::cout << *pos << std::endl;
}
//res[0]存放匹配到的完整字符串
std::cout << "match :" << res[0] << std::endl << "name:" << res[1] << std::endl;
}
4、替换。 替换匹配到的子字符串, 可以通过$N 引用第N个匹配到的值、$& 引用全匹配
#include
void TestReplace()
{
//将[email protected] 替换成[email protected]
std::string mail("[email protected]");
//建立3个子表达式
boost::regex reg("(\\w+)@(\\w+).(\\w+)");
std::cout << boost::regex_replace(mail, reg, "$1@139.$3") << std::endl;
std::cout << boost::regex_replace(mail, reg, "my$1@$2.$3") << std::endl;
//自定义替换函数,regex_replace将匹配到的字符串数组传递给回调函数,由回调函数返回新的字符串
std::cout << boost::regex_replace(mail, reg, [](const boost::smatch &m)
{
return boost::to_upper_copy(m[0].str());
}
);
}
5、迭代。 当需要从字符串中提取多个表达式时,可以采用迭代进行提取
std::string str("[email protected], [email protected], [email protected]");
boost::regex reg("(\\w+)@(\\w+).(\\w+)");
boost::sregex_iterator pos(str.begin(), str.end(), reg);
boost::sregex_iterator end;
while(pos != end)
{
std::cout << "[" << (*pos)[0] << "]";
++pos;
}
6、分词
#include
#include
void TestToken()
{
using namespace std;
using namespace boost;
string str("[email protected], [email protected], [email protected]");
regex reg("\\w+");
sregex_token_iterator pos(str.begin(), str.end(), reg);
while(pos != sregex_token_iterator())
{
cout << "[" << *pos << "]" ;
++pos;
}
cout << endl;
//如果最后一个参数args为-1,则把匹配到的字符串视为分隔符
regex split_reg(",");
pos = sregex_token_iterator(str.begin(), str.end(), split_reg, -1);
while(pos != sregex_token_iterator())
{
cout << "[" << *pos << "]" ;
++pos;
}
cout << endl;
//如果最后一个参数args为正数,则返回匹配结果的第args个子串
regex split_sub_reg("(\\w*)@(\\w*).(\\w*)");
pos = sregex_token_iterator(str.begin(), str.end(), split_sub_reg, 1);
while(pos != sregex_token_iterator())
{
cout << "[" << *pos << "]" ;
++pos;
}
cout << endl;
//匹配并指定输出顺序
//从下面字符串中提取日期,并转换成 年月日 的顺序输出
std::string input("01/02/2003 blahblah 04/23/1999 blahblah 11/13/1981");
regex re("(\\d{2})/(\\d{2})/(\\d{4})"); // find a date
int const sub_matches[] = { 3, 1, 2 }; // year,month, day
sregex_token_iterator begin( input.begin(), input.end(), re, sub_matches ), end;
// write all the words to std::cout
std::ostream_iterator< std::string > out_iter( std::cout, "\n" );
std::copy( begin, end, out_iter );
}
#include
#include
#include
using namespace std;
using namespace boost;
/*搜索字符串中是否含有子字符串
int main( int argc, char* argv[] )
{
char *buf = "This is boost::regex example boost::regex";
boost::regex exampleregex( "boost::regex" );
boost::cmatch result;
if( boost::regex_search( buf, result, exampleregex ) )
{
std::cout << result.str() << std::endl;
}
//boost::regex_replace(buf,)
return 0;
}*/
//写了个去除左侧无效字符(空格,回车,TAB)的正则表达式。
/*void main()
{
std::string testString = " /r/n Hello World ! GoodBye World/r/n";
std::string TrimLeft = "([//s//r//n//t]*)(//w*.*)";
boost::regex expression(TrimLeft);
testString = boost::regex_replace( testString, expression, "$2" );
std::cout<< "TrimLeft:" << testString <)(.+?)(?=))";
//regstr = "((?=.+))";
boost::regex expression(regstr);
std::string testString = "sdaaccfsaaccdf192dfsdbbdd.168sdfs.sdfs4dsf.sfdsd1asfscvasdf";
boost::smatch what;
std::string::const_iterator start = testString.begin();
std::string::const_iterator end = testString.end();
while( boost::regex_search(start, end, what, expression) )
{
std::cout<< "Have digit:" ;
std::string msg(what[0].first, what[0].second);
std::cout<< msg.c_str() << std::endl;
start = what[0].second;
}
}
*/
//#include "stdafx.h"
#include
#include
#include
#include
#include
using namespace std;
//using namespace boost;
boost::wregex expression(L"^//s*我+//s*[想|爱|恨|扁]+//s*你");
int main(int argc, char* argv[])
{
locale loc( "Chinese-simplified" );
wcout.imbue(loc);
std::wstring in = L"我我我我 爱爱爱爱爱 你";
static boost::wsmatch what;
cout << "enter test string" << endl;
//getline(cin,in);
if(boost::regex_match(in.c_str(), what, expression))
{
for(int i=0;i
#include
#include
int main() {
std::string str = "I'm singing while you're dancing.";
std::string pattern = "(//b//w+(?=ing//b))";
boost::regex ee_all(pattern);
boost::smatch result;
std::string::const_iterator it = str.begin();
std::string::const_iterator end = str.end();
while(boost::regex_search(it, end, result, ee_all)) {
std::cout << result[0] << '/n';
it = result[0].second;
}
}
*/
/*void main()
{
std::string testString = "sdfsaaccdf192dfsdbbdd.168sdfs.sdfs4dsf.sfdsd1asfscvasdf";
cmatch what;
regex expression( "(?=(.+?))");
if(regex_match(testString,what,expression))
{
int sun = what.size();
cout< it(s,s+std::strlen(s),reg,-1);
regex_token_iterator end;
while (it!=end)
{
cout<<*it++<