Boost::Regex代码示例

看一个别人给出的例子,当我们输入“select 字符串 from 字符串”的时候,会得到输出;如果不符合这个格式,就会输出error。注意:在命令行下输入的时候,按ctrl+Z、回车表示行输入结束。

    #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.str()<<endl;
        }
        else
        {
            cout<<"Error Input"<<endl;
        }
        return 0;
    }

regex对象与regex_match()函数

下面是一个检测两个字符串是否符合指定表达式的例子:

    #include <iostream>
    #include <cassert>
    #include <string>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    int main()
    {
        regex reg("//d{3}([a-zA-Z]+).(//d{2}|N/A)//s//1");
        string correct = "123Hello N/A Hello";
        string incorrect = "123Hello 12 hello";
        assert(regex_match(correct,reg)==true);
        assert(regex_match(incorrect,reg)==false);
        return 0;
    }

reg的格式含义是:三个数字,1个单词,一个任意字符,2个数字或者字符串N/A,1个空格,然后再重复第一个单词。

下面是一个匹配邮件地址的表达式例子:

    #include <iostream>
    #include <cassert>
    #include <string>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    int main()
    {
        regex reg("//w(.+)@(.+)//.com");
        string correct = "[email protected]";
        assert(regex_match(correct,reg)==true);
        return 0;
    }

很有意思吧!

regex_search()函数的使用

    #include <iostream>
    #include <cassert>
    #include <string>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    int main()
    {
        regex reg("(new)|(delete)");
     smatch m;
        string s = "Calls to new mustbe followed by delete.  Calling simply new results in aleak!";
     int new_counter = 0;
        int delete_counter = 0;
        string::const_iterator it = s.begin();
    //    string::const_iterator end = s.end();
        while (regex_search(it,(string::const_iterator)s.end(),m,reg))
        {
            m[1].matched ? ++new_counter : ++delete_counter;
            it = m[0].second;
        }
        if (new_counter != delete_counter)
            cout<<"Leak detected!/n";
        else
            cout<<"Seems OK.../n";
        return 0;
    }

在上面的例子中,统计new和delete这两个单词的数目是不是一样。注意:smatch对象,它其实是一个match_results类型,分 别用来记录reg中的索引是否被匹配。如果“new”被匹配了,那么m[1].matched就会为真(true);m[0].second表示it向后 移动了,继续匹配剩下的字符串。

m[0],返回的是对匹配整个正则表达式的子匹配的引用,因此可以确定这个匹配的结束点通常是下次运行regex_search函数的起始点。

regex_replace()函数的使用

顾名思义,它可以用于执行文本替换。它在输入数据中进行搜索,查找正则表达式的所有匹配,对于每个匹配,该算法调用match_results::format,并将结果输出到一个传递给该函数的输出迭代器(output iterator)中。

下面的例子将英式拼法的colour替换为美式拼法的color。如果不使用正则表达式来进行这个拼写的修改,将会非常单调乏味,而且容易出错。问 题在于单词中可能存在不同的大小写,而且单词可能还有很多的变形——例如colourize。为了正确地解决这个问题,需要把正则表达式分为3个子表达 式:

    regex reg("(Colo)(u)(r)",boost::regex::icase|boost::regex::perl);

为了在任何匹配中能够很容易地删除字母u,我们对它进行了隔离。后面的是regex构造函数的标志参数,表示这个正则表达式不区分大小写;设置格式 标志过程中的一个常见错误是忽略了regex需要默认启用的那些标志,如果没有设置这些标志,那么它们就不会启用,因此通常情况下必须使用应用应该设置的 所有标志。

在使用regex_replace替换时,我们需要以参数的方式提供一个格式化字符串,该字符串决定如何进行替换。如果我们希望保留第一个和第三个匹配的子表达式,那么可以使用$N(N为子表达式的索引)来实现。下面是解决问题的完整代码:

    #include <iostream>
    #include <cassert>
    #include <string>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    int main()
    {
        regex reg("(Colo)(u)(r)",regex::icase | regex::perl);
        string s = "Colour, colours,color,colourize";
        s = regex_replace(s,reg,"$1$3");
    //  s = regex_replace(s,reg,"$1 wocao $3");//尝试在输出字符串中加空格   cout<<s<<endl;
        return 0;
    }

关于重复和贪婪

    #include <iostream>
    #include <cassert>
    #include <string>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    int main()
    {
        regex reg("(.*)(//d{2})");
        cmatch m;
        const char * text = "Note that I‘m 31 years old, not 32.";
        if (regex_search(text,m,reg))
        {
            if (m[1].matched)
            {
                cout<<m[1].str()<<‘/n‘;
            }
            if (m[2].matched)
            {
                cout<<m[2]<<‘/n‘;
            }
        }
    }

上面代码的输出结果是:

Note that I‘m 31, not

32

也就是说,正则表达式中的".*"选项贪婪地吞掉了所有的输入!从而致使后面的子表达式无法获得匹配。按照我们的想法:31应该是符合/d{2}的条件的,应该被输出!但是可惜,它被*吞掉了。在正则表达式中,+和*都是重复性贪婪的。

为了非贪婪的重复,怎么办呢?可以在重复记号后面加一个问号"?",重复就会变成非贪婪的。修改上面代码的表达式:

regex reg("(.*?)(//d{2})");

再运行程序,结果就变成:

Note that I‘m

31

明白了吧?

regex_iterator的介绍和使用

    #include <iostream>
    #include <cassert>
    #include <string>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    class regex_callback
    {
        int sum_;
    public:
        regex_callback():sum_(0){}
        template<typename T> void operator()(const T& what)
        {
            sum_+=atoi(what[1].str().c_str());
        }
        int sum() const
        {
            return sum_;
        }
    };
    int main()
    {
        regex reg("(//d+),?");
        string s = "1,1,2,3,5,8,13,21";
        sregex_iterator it(s.begin(),s.end(),reg);
        sregex_iterator end;
        regex_callback c;
        int sum = for_each(it,end,c).sum();
    }

sregex_iterator是 regex_iterator<std::string::const_iterator>的typedef,现在的使用方法更加清晰了。我 们可以对比一下前面使用regex_search的时候,不得不在循环中手动地让起始迭代器前进,而且还要手动调用regex_search函数。

regex_token_iterator的介绍和使用

它和regex_iterator相似,但是它列举的是与正则 表达式不匹配的字符序列,该特性对于字符串分割非常有用。当解引用regex_token_iterator时,只有被“预订”的子表达式才可以返回。下 面这个例子:输入数据的条目之间用“/”分隔,要获得两个斜杠之间的数据;使用regex_token_iterator来分隔处理就特别简单,因为它的 表达式简单:regex reg("/");为了使用这个正则表达式来分割输入,需要将一个特殊的索引-1传递给regex_token_iteraotr的构造函数。

    #include <iostream>
    #include <cassert>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    int main()
    {
        regex reg("/");
        string s = "Split/Values/Separated/By/Slashes,";
        vector<string> vec;
        sregex_token_iterator it(s.begin(),s.end(),reg,-1);
        sregex_token_iterator end;
        while (it!=end)
            vec.push_back(*it++);
        assert(vec.size()==count(s.begin(),s.end(),‘/‘)+1);
        assert(vec[0]=="Split");

        return 0;
    }

regex_token_iterator是一个 模板类,sregex_token_iterator是迭代器类型,是 regex_token_iterator<std::string::const_iterator>的typedef。在上面的程序中, 每次解引用返回的都是当前的sub_match,当迭代器前进时,它会尝试再次匹配该正则表达式。

换一个不同类型的输入,也应该能够写出程序来!

    #include <string>
    #include <iostream>
    #include <cassert>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    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+strlen(s),reg,-1);
        regex_token_iterator<char*> end;
        while (it!=end)
        {
            cout<<*it++<<endl;
        }
        return 0;
    }

当需要反复调用regex_search时,考虑使用这两个iterator,比较方便。

/A和/Z的使用

如果把/A放在正则表达式的开始,把/Z放在正则表达式的最后,那么regex_search函数的行为就可以与regex_match函数的相同——也就是说,regex_search函数必须匹配所有的输入后才能匹配成功。

下面的表达式通常要求所有的输入都能获得匹配,而不管使用regex_match还是regex_search:

    regex reg("//A//d*//Z");

对比regex_search和regex_match的使用:

regex reg("//d*");
bool b=regex_match("17 is prime",reg);
//返回失败
regex reg("//d*");
bool b=regex_search("17 is prime",reg);
//返回true
regex reg("//d*");
bool b=regex_search("17 is prime",reg);
//仍然返回失败

元字符(^)的使用

元字符用来表示取反。regex reg("[^13579]");它表示一个取反的字符类,可以匹配任意非奇数的字符。

    #include <iostream>
    #include <cassert>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    int main()
    {
        regex reg("[^13579]");
        string s="0123456789";
        sregex_iterator it(s.begin(),s.end(),reg);
        sregex_iterator end;
        while (it!=end)
            cout<<*it++;
        return 0;
    }

上面程序的输出结果为“02468”,如果输入字符串是“abcd”,也会全部匹配(因为它们不是奇数)。

另外,元字符^还可以用来表示一行的开始,元字符$则表示一行的结束。

无效正则表达式与异常抛出

下面这个程序还可以当作正则表达式格式输入的练习:)

    #include <string>
    #include <iostream>
    #include <cassert>
    #include <boost/regex.hpp>
    using namespace std;
    using namespace boost;
    int main()
    {
        cout<<"Enter a regular expression:/n";
        string s;
        getline(cin,s);
        try
        {
            regex reg(s);
            cout<<"Now enter a string to be matched:/n";
            getline(cin,s);
            if (regex_match(s,reg))
                cout<<"That‘s right!/n";
            else
                cout<<"No, that doesn‘t match!";
        }
        catch (bad_expression & e)
        {
            cout<<"That‘s not a valid expression! Error: "<<e.what()<<endl;
        }
        return 0;
    }

输入/d{5},输入:12345,输出:That‘s right!(奇怪,为什么这里输入/d而不是//d呢?输入//d没有抛出异常,却不能正确匹配!如果我输入//d,而这又是一个合法的正则表达式,那么它的匹配字符串是怎样的?)

输入错误的正则表达式:(/w*)),程序会抛出异常。

参考文献:超越c++标准库 Boost

时间: 2024-10-10 09:35:40

Boost::Regex代码示例的相关文章

Boost signal 代码示例

网上介绍Boost signal原理的文章很多,这里不介绍原理,仅贴一些示例代码,这在初步接触Boost signal时能够有个较好的感性认识,深入了解需要去体会挖掘boost源码.代码基本上来自Boost turioal,其中有一些错误会导致编译不过,这里都做了更正: 1. 基本运用 #include <boost/signals2.hpp> #include <boost/bind.hpp> #include <iostream> using namespace s

#墙裂推荐Boost regex# C,C++11,Boost三种regex库性能比较

在最近的一个项目中,发现之前的正则匹配模块对于长字符串匹配性能损失比较厉害,因此对长字符串下的各种正则匹配进行了略微研究并附有实例.本文参考了博客http://www.cnblogs.com/pmars/archive/2012/10/24/2736831.html(下文称文1),这篇文章也是对三种regex库进行了比较,但有些地方我还有一些自己的见解,特此罗列如下,感谢这篇文章的作者. 1.C regex库 由于项目中一直用的都是C regex库,所以首先对C regex进行了研究.对于C r

boost::string or boost::regex

有时候写代码时会遇到下面问题 如果有一个文本文件,其包括内容类似于C语言,当中有一行例如以下格式的语句: layout (local_size_x = a,local_size_y = b, local_size_z = c) in; 当中用蓝色标记出的部分(layout, local_size_x, local_size_y, local_size_z, in)为keyword,斜体字部分(a, b, c)为数据类型为unsigned int的数字,请编写一个函数,用于从文件里抽取出a, b,

vs 2005 使用 boost regex

第一步: Boost 入门及其VS2005下编译boost库 boost.regex库安装指南 Boost下载和Boost安装去哪下载Boost呢?英文http://www.boost.org ,中文http://boost.c-view.org,可以找到一个.zip或.tar.gz格式的压缩包.下载完毕后,解压到某个目录,比如boost_1_26_0,里面一般有这么几个子目录:boost.libs.more.people.status.tools,看看没问题就行了.如果Boost更新时您懒得去

计算DXFReader中多边形的面积代码示例

在DXFReader中, 一般的多边形的面积计算绝对值 其中K表是顶点的数目,它们的坐标,用于在求和和, 所以用下面的代码就可以计算出一个封闭的多段线的区域: view source print? 01 Dim Vertex As Object 02 Dim Entity As Object 03 Dim k As Long 04 Dim i As Long 05 Dim Area As Single 06 07 With DXFReader1 08 09  For Each Entity In

代码示例:一些简单技巧优化JavaScript编译器工作详解,让你写出高性能运行的更快JavaScript代码

告诉你一些简单的技巧来优化JavaScript编译器工作,从而让你的JavaScript代码运行的更快.尤其是在你游戏中发现帧率下降或是当垃圾回收器有大量的工作要完成的时候. 单一同态: 当你定义了一个两个参数的函数,编译器会接受你的定义,如果函数参数的类型.个数或者返回值的类型改变编译器的工作会变得艰难.通常情况下,单一同态的数据结构和个数相同的参数会让你的程序会更好的工作. function example(a, b) { // 期望a,b都为数值类型 console.log(++a * +

jquery操作单选钮代码示例

jquery操作单选钮代码示例:radio单选按钮是最重要的表单元素之一,下面介绍一下常用的几个jquery对radio单选按钮操作.一.取消选中: $(".theclass").each(function(){ if($(this).attr('checked')) { $(this).attr('checked',false); } }); 以上代码可以将class属性值为theclass的被选中单选按钮取消选中.二.获取被选中的单选按钮的值: var val=$('.thecla

Python实现各种排序算法的代码示例总结

Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示例总结,其实Python是非常好的算法入门学习时的配套高级语言,需要的朋友可以参考下 在Python实践中,我们往往遇到排序问题,比如在对搜索结果打分的排序(没有排序就没有Google等搜索引擎的存在),当然,这样的例子数不胜数.<数据结构>也会花大量篇幅讲解排序.之前一段时间,由于需要,我复习了

领域驱动开发推荐代码示例 — Microsoft NLayerApp

简介: Microsoft NLayerApp是由微软西班牙团队出品的基于.NET 4.0的“面向领域N层分布式架构”代码示例,在codeplex上的地址是:http://microsoftnlayerapp.codeplex.com/. 架构图: 点击查看大图 代码下载:http://microsoftnlayerapp.codeplex.com/releases/view/56660 所用到的软件: - Microsoft Visual Studio 2010  - Microsoft Ex