工作需要用到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 match\n");             else                 printf("ok\n");                 */}}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%s\n********\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");elseprintf("ok\n");}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++正则怎么用啊?那90%的人会推荐你用boost正则,他实现起来方便,正则库也很强大,资料可以找到很多,所以我也不在阐述了。

4、对比情况

总结:

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了。

作者:pmars的博客

来源:51CTO

C++中三种正则表达式比较相关推荐

  1. C++中三种正则表达式比较(C regex,C ++regex,boost regex)

    原文地址:https://www.cnblogs.com/pmars/archive/2012/10/24/2736831.html 工作需要用到C++中的正则表达式,所以就研究了以上三种正则. 1, ...

  2. Linux 中三种引号(单引号、双引号、反引号)的区别

    1.双引号 保护特殊元字符和通配符不被 shell 解析,但是允许变量和命令的解析,以及转义符的解析. 2.单引号 单引号内不允许任何变量.元字符.通配符.转义符被 shell 解析,均被原样输出. ...

  3. pl/sql中三种游标循环效率对比

    pl/sql中三种游标循环效率对比 - Oracle数据库栏目 - 红黑联盟 http://www.2cto.com/database/201307/224636.html 转载于:https://b ...

  4. 简单介绍Lua中三种循环语句的使用

    今天小编就为大家分享一篇关于Lua中三种循环语句的使用讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧 Lua的循环和C语言的循环的语法其实差不多,所以, ...

  5. zynq学习03 zynq中三种实现GPIO的方式

    http://m.blog.csdn.net/article/details?id=52123465 http://blog.chinaaet.com/songhuangong/p/43084 本文介 ...

  6. C#中三种定时器对象的比较

    ·关于C#中timer类 在C#里关于定时器类就有3个 1.定义在System.Windows.Forms里 2.定义在System.Threading.Timer类里 3.定义在System.Tim ...

  7. VMware vSphere中三种磁盘:精简置备/厚置备置零/厚置备延迟置零

    有时候我们可能会遇到这样几种现象:虚拟机置备100G,但是平台上却显示虚拟机使用了500G存储? 平台上看到所有虚拟机加起来才3T,存储上5T的空间却没了,严重的还导致所有虚拟机宕机. 为啥?都是&q ...

  8. Extjs中三种不同的数据提交方式

    Extjs中三种不同的数据提交方式 Extjs的三种提交方式: 表单Ajax提交,普通提交,单独Ajax提交: 1.表单ajax提交(默认提交方式) 提交函数:当按下表单中的提交按钮时执行下面的btn ...

  9. .NetCore中三种注入方式的思考

    .NetCore中三种注入方式的思考 原文:.NetCore中三种注入方式的思考 该篇内容由个人博客点击跳转同步更新!转载请注明出处! .NetCore彻底诠释了"万物皆可注入"这 ...

最新文章

  1. 二进制计算机课教案,计算机与二进制教案.pdf
  2. Spring Boot 极简集成 Shiro
  3. 大众点评字体_点评里的神笔马良!她的美食笔记会让你惊掉下巴!
  4. 【算法入门】用Python手写五大经典排序算法,看完这篇终于懂了!
  5. linux下ARP防御
  6. wamp无法使用php,使用wamp无法访问www中的php文件
  7. vscode中如何创新建php文件,vscode如何创建代码模板
  8. django中collectstatic的使用
  9. linux DHCP多作用域
  10. sas9.4安装教程
  11. 四川婚姻登记捷宇SC10T高拍仪技术规格说明书
  12. excel 小技巧选某些列的时候总是选到后面的空的部分解决方法
  13. 怎么解决ZBrush保存历史记录太多问题
  14. 数据分析实战——淘宝母婴用品购买情况
  15. javaWeb(1)———基础
  16. [Andriod官方训练教程]管理Activity的生命活动之开始一个Activity
  17. MFC隐藏主窗口运行的几种方法
  18. iOS15只是一个更好看的Linux吗?
  19. hive 常用正则表达式
  20. HIve窗口函数之CUME_DIST,PERCENT_RANK

热门文章

  1. android 5.0主题风格研究
  2. 用户接口设计的20个原则
  3. 自己开发的Grid组件 针对IOS的
  4. 华为S5348交换机基本配置
  5. AAA及Radius
  6. SaltStack入门(二)Grains、NoteGroup和State
  7. 易邮邮箱服务器的安装和配置
  8. [译] 解密 Airbnb 的数据科学部门如何构建知识仓库
  9. awbeci网站之技术篇
  10. JDBC 实例--JDBC通过工具类DBUtil连接到数据库,让我们不再恐惧操作数据库