新普京网站-澳门新普京 > 前端 > 中三种正则表达式比较

中三种正则表达式比较

2019/12/30 02:00

办事亟待用到C++中的正则表明式,所以就研究了以上三种正则。

1、C regex

/*  write by xingming
 *  time:2012年10月19日15:51:53
 *  for: test regex
 *  */

#include <regex.h>
#include <iostream>
#include <sys/types.h>
#include <stdio.h>
#include <cstring>
#include <sys/time.h>

using namespace std;
const int times = 1000000;

int main(int argc,char** argv)
{
    char pattern[512]="finance.sina.cn|stock1.sina.cn|3g.sina.com.cn.*(channel=finance|_finance$|ch=stock|/stock/)|dp.sina.cn/.*ch=9&";
    const size_t nmatch = 10;
    regmatch_t pm[10];
    int z ;
    regex_t reg;
    char lbuf[256]="set",rbuf[256];
    char buf[3][256] = {"finance.sina.cn/google.com/baidu.com.google.sina.cndddddddddddddddddddddda.sdfasdfeoasdfnahsfonadsdf",
                    "3g.com.sina.cn.google.com.dddddddddddddddddddddddddddddddddddddddddddddddddddddbaidu.com.sina.egooooooooo",
                    "http://3g.sina.com.cn/google.baiduchannel=financegogo.sjdfaposif;lasdjf.asdofjas;dfjaiel.sdfaosidfj"};
    printf("input strings:n");
    timeval end,start;
    gettimeofday(&start,NULL);
    regcomp(&reg,pattern,REG_EXTENDED|REG_NOSUB);
    for(int i = 0 ; i < times; ++i)
    {
        for(int j = 0 ; j < 3; ++j)
        {
            z = regexec(&reg,buf[j],nmatch,pm,REG_NOTBOL);
/*          if(z==REG_NOMATCH)
                printf("no matchn");
            else
                printf("okn");
                */
        }
    }
    gettimeofday(&end,NULL);
    uint time = (end.tv_sec-start.tv_sec)*1000000 + end.tv_usec - start.tv_usec;
    cout<<time/1000000<<" s and "<<time%1000000<<" us."<<endl;
    return 0 ;
}

采用正则表明式可总结的分成几步:

  • 1.编写翻译正则表明式
  • 2.施行相配
  • 3.保释内存

先是,编写翻译正则表达式

int regcomp(regex_t *preg, const char *regex, int cflags);

reqcomp(卡塔尔(قطر‎函数用于把正则表明式编写翻译成某种格式,能够使前面包车型地铁同盟更有效。

preg: regex_t构造体用于寄放编写翻译后的正则表明式;

regex: 指向正则表达式指针;

cflags:编写翻译形式

共有如下各类编写翻译形式:

REG_EXTENDED:使用效果越来越强硬的扩张正则表明式

REG_ICASE:忽视大小写

REG_NOSUB:不用存款和储蓄匹配后的结果

REG_NEWLINE:识别换行符,那样‘$’就足以从行尾开端相配,‘^’就能够从行的早先最初相配。不然忽视换行符,把全体文本串当作一个字符串管理。

扶助,推行相配

int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);

preg: 已编写翻译的正则表明式指针;

string:目的字符串;

nmatch:pmatch数组的长度;

pmatch:构造体数组,存放相配文本串的岗位音信;

eflags:相配情势

共三种相称格局:

REG_NOTBOL:The match-beginning-of-line operator always fails to match  (but see  the  compilation  flag  REG_NEWLINE above). This flag may be used when different portions of a string are passed  to  regexec and the beginning of the string should not be interpreted as the beginning of the line.

REG_NOTEOL:The match-end-of-line operator always fails to  match  (but  see the compilation flag REG_NEWLINE above)

最终,释放内存

void regfree(regex_t *preg);

当使用完编写翻译好的正则表明式后,大概需求重新编写翻译其余正则表达式时,一定要动用这些函数清空该变量。

别的,管理错误

size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);

当推行regcomp 大概regexec 发生错误的时候,就足以调用那个函数而回到二个饱含错误消息的字符串。

errcode: 由regcomp 和 regexec 函数再次回到的谬误代号。

preg: 已经用regcomp函数编译好的正则表达式,那么些值可认为NULL。

errbuf: 指向用来存放在错误信息的字符串的内部存款和储蓄器空间。

errbuf_size: 指明buffer的长短,假若这几个错误音信的长短超过那些值,则regerror 函数会自动截断超出的字符串,但她依然会重回完整的字符串的尺寸。所以大家得以用如下的主意先得到错误字符串的长度。

本来小编在测验的时候使用的也比较轻易,所以就一贯用了,速度一会再说!

2、C++ regex

/*  write by xingming
 *  time:2012年10月19日15:51:53
 *  for: test regex
 *  */

#include <regex>
#include <iostream>
#include <stdio.h>
#include <string>

using namespace std;

int main(int argc,char** argv)
{
    regex pattern("[[:digit:]]",regex_constants::extended);
    printf("input strings:n");
    string buf;

    while(cin>>buf)
    {
        printf("*******n%sn********n",buf.c_str());

        if(buf == "quit")
        {
            printf("quit just now!n");
            break;
        }

        match_results<string::const_iterator> result;
        printf("run compare now!  '%s'n", buf.c_str());
        bool valid = regex_match(buf,result,pattern);
        printf("compare over now!  '%s'n", buf.c_str());

        if(!valid)
            printf("no match!n");
        else
            printf("okn");
    }

    return 0 ;
}

C++这一个纯真不想多说它,测量试验进程中发掘 字符相称的时候 ‘a’ 是足以宽容的,a+也是足以的,[[:w:]]也足以包容任性字符,但[[:w:]]+就只能协作三个字符,+号貌似不起功效了。所今后来就干脆吐弃了那庞大的C++正则,假诺有大牌知道这里面我错在哪个地方了,真心谢谢你告诉本人弹指间,多谢。

3、boost regex

/* write by xingming
 * for:test boost regex
 * time:2012年10月23日11:35:33
 * */

#include <iostream>
#include <string>
#include <sys/time.h>
#include "boost/regex.hpp"

using namespace std;
using namespace boost;
const int times = 10000000;

int main()
{
    regex  pattern("finance\.sina\.cn|stock1\.sina\.cn|3g\.sina\.com\.cn.*(channel=finance|_finance$|ch=stock|/stock/)|dp\.s
ina\.cn/.*ch=9&");
    cout<<"input strings:"<<endl;
    timeval start,end;
    gettimeofday(&start,NULL);
    string input[] = {"finance.sina.cn/google.com/baidu.com.google.sina.cn",
                      "3g.com.sina.cn.google.com.baidu.com.sina.egooooooooo",
                      "http://3g.sina.com.cn/google.baiduchannel=financegogo"};
    for(int i = 0 ;i < times; ++ i)
    {
        for(int j = 0 ; j < 3;++j)
        {
            //if(input=="quit")
            //  break;
            //cout<<"string:'"<<input<<'''<<endl;
            cmatch what;
            if(regex_search(input[j].c_str(),what,pattern)) ;
            //  cout<<"OK!"<<endl;
            else ;
            //  cout<<"error!"<<endl;
        }
    }
    gettimeofday(&end,NULL);
    uint time = (end.tv_sec-start.tv_sec)*1000000 + end.tv_usec - start.tv_usec;
    cout<<time/1000000<<" s and "<<time%1000000<<" us."<<endl;
    return 0 ;
}

boost正则不用多说了,借使出去问,C++正则怎么用啊?那十分九的人会推荐您用boost正则,他达成起来方便,正则库也很苍劲,资料可以找到比相当多,所以作者也不在演讲了。

4、相比较意况

图片 1

总结:

C regex的进度让自身大吃豆蔻梢头惊啊,相比较boost的进程,C regex的速度大致要快上3倍,看来正则引擎的接收上应该有着落了!

地点的报表中本身使用的正则和字符串是豆蔻年华律的(在代码中C regex的被自个儿加长了),速度相差差不离有3倍,C的速度差非常少在30+w/s , 而boost的速度基本在15-w/s ,所以比较就出去了!

在那间Cregex的速度很让自身吃惊了已经,但随时作者的测验更让自家振憾。

自身曾在.net正则方面接触的可比多,就写了贰个.net版本的作为对照

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace 平常测试
{
    class Program
    {
        static int times = 1000000;
        static void Main(string[] args)
        {
            Regex reg = new Regex(@"(?>finance.sina.cn|stock1.sina.cn|3g.sina.com.cn.*(?:channel=finance|_finance$|ch=stock|/stock/)|dp.sina.cn/.*ch=9&)",RegexOptions.Compiled);
            string[] str = new string[]{@"finance.sina.cn/google.com/baidu.com.google.sina.cn",
                    @"3g.com.sina.cn.google.com.baidu.com.sina.egooooooooo",
                    @"http://3g.sina.com.cn/google.baiduchannel=financegogo"};
            int tt = 0;
            DateTime start = DateTime.Now;
            for (int i = 0; i < times; ++i)
            {
                for (int j = 0; j < 3; ++j)
                {
                    if (reg.IsMatch(str[j])) ;
                        //Console.WriteLine("OK!");
                    //else
                        //Console.WriteLine("Error!");
                }
            }
            DateTime end = DateTime.Now;
            Console.WriteLine((end - start).TotalMilliseconds);
            Console.WriteLine(tt);
            Console.ReadKey();
        }
    }
}

结果发掘,正则在不开展RegexOptions.Compiled 的时候,速度和C regex的基本雷同,在编写翻译只会,速度会比C regex快上大器晚成倍,那不由得让自家对微软的那群人的敬畏之情自可是然啊。

但随着笔者去查看了一下该博客下边C regex的陈说,开采笔者能够再表明正则的时候出席编写翻译情势,随后我步入了上边代码里的 REG_NOSUB(在那前测量试验的时候是从未投入的),结果让自身激情面很感动的快慢出来了,C regex 相配速度依旧高达了 300+w/s,也等于比原本的(不步向REG_NOSUB卡塔尔国的代码快了附近10倍。

之后小编改造了同盟的字符串,将其长度生了生机勃勃倍,达到每种100字符左右(代码里面所示),相配速度就下去了,但是也能完毕100w/s左右,那自然满意我们今后的须要了。

结果很明朗,当然会选用C regex了。

上一篇:没有了 下一篇:没有了