Boost学习之正则表达式--regex-阿里云开发者社区

开发者社区> shadowcat> 正文

Boost学习之正则表达式--regex

简介: 来源: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:
+关注继续查看

来源: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编码的支持
        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);

Boost Regex Libray类和接口介绍
(1)basic_regex
basic_regex是一个模板类,它封装了正则表达式的解析和编译,它是Boost.Regex中用来表示正则表达式的对象类型。Boost.Regex定义了两种标准类型,一种是基于单字节字符的regex,另一种是基于宽字符的wregex
关于basic_regex提供的接口,和STL中basic_string所提供的十分类似,具体可以参考:
http://www.boost.org/doc/libs/1_37_0/libs/regex/doc/html/boost_regex/ref/basic_regex.html

(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 <string>   
#include <iostream>   
#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.*)");

注意使用Boost.Regex需要预先编译

完整编译请参考本站编译Boost的文章
如果只要编译Regex库,有两种方法(参考链接):
  1. 在Boost根目录下运行bjam --toolset=<编译器名> --with-regex 其它参数
  2. \libs egex\build里,找到对应编译器的makefile,然后make -f xxxx.mak

使用

模板类:
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。

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 <boost/regex.hpp>

示例代码 :先准备一个测试用的数据备用,如果各位有雅兴可以参考本站的另一篇文章《Google Testing》使用Google Testing框架来做这个实验,花一样时间学两样啊~~

#include <iostream>
#include <boost/regex.hpp>

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(); //暂停
}

1.字符串匹配

要确定一行字符串是否与指定的正则表达式匹配,使用regex_match
下面这个代码可以验证szStr字串(定义在上面)是否与szReg匹配。

    {    //字符串匹配
        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函数。
一个sub_match就是一个子串,它从std::pair继承而来,这个迭代器pair里的firstsecond分别指向了这个子串开始和结尾所在位置。同时,sub_match又提供了str(),length()方法来返回整个子串。

2.查找字符串

regex_match只验证是否完全匹配,如果想从一大串字符串里找出匹配的一小段字符串(比如从网页文件里找超链接),这时就要使用regex_search了。
下面这段代码从szStr中找数字

    { //查找
        boost::cmatch mat;
        boost::regex reg( "\\d+" );    //查找字符串里的数字
        if(boost::regex_search(szStr, mat, reg))
        {
            cout << "searched:" << mat[0] << endl;
        }
    }

3.替换

regex_replace提供了简便的方法来部分替换源字符串
正则表达式中,使用$1~$9\1~\9)表示第几个子串,$&表示整个串,$`表示第一个串,$'表示最后未处理的串。

    { //替换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;
    }

4.使用regex_iterator查找

对应于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 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);

5.使用regex_token_iterator拆分字符串

它同样也有四个特化,形式和上面类似,就不再写一遍骗篇幅了。
    这个迭代器的value_type定义是一个sub_match

    { //使用迭代器拆分字符串
        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;
        }
    }

参考

正则表达式教程
联机文档

联机文档里几个不错的例子:

regex_search示例,演示找出C++代码中所有的类定义
regex_replace示例,演示以C/C++代码作为输入,输出代码高亮的HTML代码
regex_iterator示例,regex_search示例的regex_iterator实现
regex_token_iterator示例,第二个例子演示了从一个HTML文件里提取出所的有链接地址

完整测试代码:

#include <iostream>
#include <boost/regex.hpp>

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;
}

1、完全匹配
    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 = "tengxun@qq.com";
    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 = "tengxun@qq.com.cn";
    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 <boost/algorithm/string.hpp>
void TestReplace()
{
    //将tengxun@qq.com.cn 替换成tengxun@139.com.cn
    std::string mail("tengxun@qq.com.cn");
    //建立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("tengxun@qq.com, aa@tt.com, bb@qq.com");
    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 <iostream>
#include <boost/regex.hpp>
void TestToken()
{
    using namespace std;
    using namespace boost;
    string str("tengxun@qq.com, aa@tt.com, bb@qq.com");
    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 <iostream>
#include <boost/regex.hpp>
#include <string>
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 <<std::endl;
}*/
//关于重复的贪婪
/*void main()
{
    std::string regstr = "(.*?)(age)(.*?)(//d{2})";
    boost::regex expression(regstr);
    std::string testString = "My age is 28 His age is 27";
    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::string name(what[1].first, what[1].second);
        std::string age(what[4].first, what[4].second);
        std::cout<< "Name:" << name.c_str() << std::endl;
        std::cout<< "Age:" <<age.c_str() << std::endl;
        start = what[0].second;
    }
    
}*/
  
//regex_search学习
//regex_search与regex_match基本相同,只不过regex_search不要求全部匹配,即部份匹配(查找)即可。
//检测字符串里是否含有数字
//简单例子:
/*void main()
{
    std::string regstr = "(//d+)";
    boost::regex expression(regstr);
    std::string testString = "192.168.4.1";
    boost::smatch what;
    if( boost::regex_search(testString, expression) )
    {
        std::cout<< "Have digit" << std::endl;
    }
}
//用于打印出所有的数字
void main()
{
    std::string regstr = "(//d+)";
    regstr = "(?<=(<a href="/" mce_href="/"")(.+?)(/">)(.+?)(?=</a>))";
    //regstr = "((?=<a href="/" mce_href="/"").+(?=/">.+</a>))";
    boost::regex expression(regstr);
    std::string testString = "sd<a href="/" mce_href="/""http:/www.baidu.com//" target='_blank'>aacc</a>fs<a href="/" mce_href="/""http:/www.baidu.com//">aacc</a>df192dfsd<a href="/" mce_href="/""http:/www.gjw123.com//">bbdd</a>.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 <cstdlib>
#include <stdlib.h>
#include <boost/regex.hpp>
#include <string>
#include <iostream>
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<what.size();i++)
            wcout<<L"str :"<<what[i].str()<<endl;
    }
    else
    {
        wcout<<L"Error Input"<<endl;
    }
     
    return 0;
}
  
/*
#include <iostream>
#include <string>
#include <boost/regex.hpp>
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 = "sdfs<a href="/" mce_href="/""http:/www.baidu.com//">aacc</a>df192dfsd<a href="/" mce_href="/""http:/www.gjw123.com//">bbdd</a>.168sdfs.sdfs4dsf.sfdsd1asfscvasdf";
    cmatch what;
    regex expression( "(?=<a//s+href=/"(.+?)/">(.+?)</a>)");
    if(regex_match(testString,what,expression))
    {
        int sun = what.size();
        cout<<sun<<endl;
        
        for(int i=0;i <what.size();i++);
            cout << "str: " <<what.str() <<endl;
    }
    else
    {
        cout << "Error "<<endl;
    }
    
}*/
/*
四:regex_match例子代码学习
1 我们经常会看一个字符串是不是合法的IP地址,合法的IP地址需要符合以下这个特征:
  xxx.xxx.xxx.xxx 其中xxx是不超过255的整数
正则表达式找到上面的这种形式的字符串相当容易,只是判断xxx是否超过255就比较困难了(因为正则表达式是处理的文本,而非数字)
OK,我们先来处理一个数字,即:xxx。找到一种表达式来处理这个数字,并且保证这个数字不会超过255
第一种情况:x,即只有一个数字,它可以是0~9 ,用/d 表示
第二种情况:xx,即有两个数字,它可以是00~99,用/d/d 表示
第三种情况:xxx,这种情况分为两种,一种是 1xx,可以用 1/d/d 表示
                                   另外一种是 2xx,这又分为两种 2[1234]/d
                                                             和 25[12345]
好了组合起来
1?/d{1,2}|2[1234]/d|25[12345]
既可以标识一个不大于255的数字字符串
嗯,我们现在需要重复这种情况既可:
(1?/d{1,2}|2[1234]/d|25[12345])/.(1?/d{1,2}|2[1234]/d|25[12345])/.(1?/d{1,2}|2[1234]/d|25[12345])/.(1?/d{1,2}|2[1234]/d|25[12345])
呵呵,长是长了点,我试图用boost支持的子表达式缩短,但是没有达到效果,请各位了解boost的正则表达式的达人指点:
(1?/d{1,2}|2[1234]/d|25[12345])/./1$/./1$/./1$
(参看反向索引:http://www.boost.org/libs/regex/doc/syntax_perl.html
似乎反向只能匹配与第一个字符完全一样的字符串,与我们的需求不同)
Example:
 
void main()
{
    std::string regstr = "(1?//d{1,2}|2[1234]//d|25[12345])//.(1?//d{1,2}|2[1234]//d|25[12345])//.(1?//d{1,2}|2[1234]//d|25[12345])//.(1?//d{1,2}|2[1234]//d|25[12345])";
    boost::regex expression(regstr);
    std::string testString = "192.168.4.1";
    std::cout << "enter test string" << std::endl;
    std::getline(std::cin,testString);
    if( boost::regex_match(testString, expression) )
    {
        std::cout<< "This is ip address" << std::endl;
    }
    else
    {
        std::cout<< "This is not ip address" << std::endl;
    }
    std::getline(std::cin,testString);
}
*/
//这个例子会把所有的IP的单个数字答应出来
//
/*void main()
{
    std::string regstr = "(1?//d{1,2}|2[1234]//d|25[12345])//.(1?//d{1,2}|2[1234]//d|25[12345])//.(1?//d{1,2}|2[1234]//d|25[12345])//.(1?//d{1,2}|2[1234]//d|25[12345])";
    boost::regex expression(regstr);
    std::string testString = "192.168.4.1";
    boost::smatch what;
    if( boost::regex_match(testString, what, expression) )
    {
        std::cout<< "This is ip address" << std::endl;
        for(int i = 1;i <= 4;i++)
        {
            std::string msg(what[i].first, what[i].second);
            std::cout<< i << ":" << msg.c_str() << std::endl;
        }
    }
    else
    {
        std::cout<< "This is not ip address" << std::endl;
    }
    
}*/
/*
void main()
{
    std::string regstr = "a+";
    boost::regex expression(regstr);
    std::string testString = "aaa";
    // 匹配至少一个a
    if( boost::regex_match(testString, expression) )
    {
        std::cout<< "Match" << std::endl;
    }
    else
    {
        std::cout<< "Not Match" << std::endl;
    }
}*/
  
/*
找出非奇数字符
元字符用来表示取反。regex reg("[^13579]");它表示一个取反的字符类,可以匹配任意非奇数的字符。
void main()
{
    regex reg("[^13579]");
    string s="012abcd3456789";
    sregex_iterator it(s.begin(),s.end(),reg);
    sregex_iterator end;
    while (it!=end)
        cout<<*it++;
}
*/
  
//当需要反复调用regex_search时,考虑使用这两个iterator,比较方便。
/*int main()
{
    regex reg(" ");
    char* s="123 456 789 12345";
    
// cregex_token_iterator it; //This is correct, too.
    regex_token_iterator<char*> it(s,s+std::strlen(s),reg,-1);
    regex_token_iterator<char*> end;
    while (it!=end)
    {
        cout<<*it++<<endl;
    }
    return 0;
}
*/ 


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
正则表达式(四):Java regex
以下示例所使用 Java 版本为: 1.8.0 有了上一章 python 中的 re 模块的铺垫(正则表达式(三):python re模块),对于 Java 中正则的使用理解上会简单许多。
762 0
boost uuid 学习笔记
#include #include #include #include #include using namespace boost::uuids;using namespace std;int main(){ //------------------------- // 一些std函数的应用 //...
960 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4483 0
【Spark Summit East 2017】从巨型图中学习的神经网络
本讲义出自Daniel Darabos与Hanna Gabor 在Spark Summit East 2017上的演讲,为了应对在构建神经网络的训练过程中对于图形顶点的考虑问题的挑战,Daniel Darabos与Hanna Gabor和团队使用同一张图执行预测和训练的过程并且给出了一些训练的技巧,而为了应对图过大而无法在单个机器的内存内进行真正的资源密集型计算的问题,使用对于图的分布式存储和计算策略,同时还展示了来解决上述问题核心算法以及一些实验结果。
1617 0
机器学习入门|集成学习(boosting,bagging)
集成学习,顾名思义,把多个学习算法结合起来,以达到比单一学习算法更优秀,泛化性能更好的学习算法。
2243 0
Elasticsearch学习方法分享(真实有效)
Elasticsearch Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎。它允许您快速,近实时地存储,搜索和分析大量数据。
1844 0
oracle正则表达式regexp_like用法
/*ORACLE中的支持正则表达式的函数主要有下面四个:1,REGEXP_LIKE :与LIKE的功能相似2,REGEXP_INSTR :与INSTR的功能相似3,REGEXP_SUBSTR :与SUBSTR的功能相似4,REGEXP_REPLACE :与REPLACE的功能相似它们在用法上与Oracle SQL 函数LIKE、INSTR、SUBSTR 和REPLACE 用法相同,但是它们使用POSIX 正则表达式代替了老的百分号(%)和通配符(_)字符。
817 0
+关注
shadowcat
酱油程序猿 CSDN 博客:http://blog.csdn.net/freeking101
155
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载