c++11 regex 与 PCRE库使用

  • 简介
    • PCRE
    • C++11 regex
  • 示例
    • pcre库捕获特殊字符串示例
    • c++11库捕获特殊字符串示例
  • 正则支持对比
  • 性能对比
  • 源代码

简介

PCRE

PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 perl 兼容的正则表达式库。这些在执行正规表达式模式匹配时用与Perl 5同样的语法和语义是很有用的。Boost太庞大了,使用boost regex后,程序的编译速度明显变慢。测试了一下,同样一个程序,使用boost::regex编译时需要3秒,而使用pcre不到1秒。因此改用pcre来解决C语言中使用正则表达式的问题

C++11 regex

c++ regex 库,是c++11标准引入的功能,通过 #include <regex>来使用。其中主要的算法为regex_search, regex_match, regex_replace

示例

假如我们需要处理一段特殊字符串,分析其特征发现使用正则可以很好的捕获想要获取的数据,假设这段字符串为"Makefile auth auth.c gen_sig.c gensig license.lic",我们需要字符串里面的文件名,下面使用c pcre库和c++11 regex简单实现捕获特殊字符串数据(不使用boost regex原因是Boost太庞大了,使用boost regex后,程序的编译速度明显变慢)。


pcre库捕获特殊字符串示例

首先对pcre库函数进行简单的封装(需要引入头文件#include <pcre.h> 需要链接 -lpcre),这样会更方便使用,函数如下:

///
//函数说明 :  pcre正则解析字符串
//参数说明 :  [pSubject]  规则字符串
//           [nSubjectLen]   字符串长度
//           [pPattern]    正则规则
//           [pMatchVec]    捕获字符串偏移量
//           [nMatchVec]    捕获字符串偏移量的最大长度
//           [nMatchGroup]   捕获组数
//返回值   :  true代表命中规则,false代表未命中
//作者     :  buding
//修改日期 :  2021-09-22
bool PcreMatchCapture(char* pSubject, size_t nSubjectLen, const char* pPattern, int* pMatchVec, size_t nMatchVec, int& nMatchGroup)
{pcre* pPcre = NULL;const char* pError = NULL;int nErrorOffset = 0;pPcre = pcre_compile(pPattern, 0, &pError, &nErrorOffset, NULL);if (!pPcre){printf("[pcre] compile failed at offset %d: %s\n", nErrorOffset, pError);return false;}nMatchGroup = pcre_exec(pPcre, NULL, pSubject, nSubjectLen, 0, 0, pMatchVec, nMatchVec);if (nMatchGroup < 0){pcre_free(pPcre);return false;}pcre_free(pPcre);return true;
}

分析字符串"Makefile auth auth.c gen_sig.c gensig license.lic"不难发现字符串特征都是以空白隔开的,其正则表达式也很容易写出(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s(\S+) (\S: 匹配任何可见字符。等价于[^ \f\n\r\t\v] ; \s: 匹配任何不可见字符,包括空格、制表符、换页符等等,等价于[ \f\n\r\t\v])。
正则表达式语法网上资料很多,这里就不做过多解释了。
接下来就要解析字符串中的特定内容:代码如下:

///
//函数说明 :  pcre正则解析字符串
//参数说明 :  [linedata]  规则字符串
//           [cb_arg]   回调参数,返回捕获特定内容
//返回值   :  无
//作者     :  buding
//修改日期 :  2021-09-22
void * MatchStrFileName(std::string linedata, void *cb_arg)
{int nMatchGroup = 0;int MatchVec[30] = {0};// 特殊符号'\'在程序中需要转义std::string regex = "(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s(\\S+)";if(PcreMatchCapture((char *)linedata.c_str(), linedata.size(), regex.c_str(), MatchVec, 30, nMatchGroup)){//字符串中有7组数据命中(特定字符组数 + 1)if(nMatchGroup == 7){std::string makefile(linedata.c_str()+MatchVec[2],MatchVec[3] - MatchVec[2]);printf("one hit data:%s\n", makefile.c_str());std::string auth(linedata.c_str()+MatchVec[4],MatchVec[5] - MatchVec[4]);printf("two hit data:%s\n", auth.c_str());std::string authfile(linedata.c_str()+MatchVec[6],MatchVec[7] - MatchVec[6]);printf("three hit data:%s\n", authfile.c_str());std::string gensigfile(linedata.c_str()+MatchVec[8],MatchVec[9] - MatchVec[8]);printf("four hit data:%s\n", gensigfile.c_str());std::string gensig(linedata.c_str()+MatchVec[10],MatchVec[11] - MatchVec[10]);printf("five hit data:%s\n", gensig.c_str());std::string licensefile(linedata.c_str()+MatchVec[12],MatchVec[13] - MatchVec[12]);printf("six hit data:%s\n", licensefile.c_str());}}
}

回调函数定义: typedef void *(*Callback)(std::string,void *);

输出结果如下:


c++11库捕获特殊字符串示例

首先需要引进头文件#include <regex>,其次在代码编译是需要链接 --std=c++11。或者Makefile中加入CFLAGS += --std=c++11
regex 库提供三个最基本的正则表达式函数

  • regex_match -> 完全匹配
  • regex_search -> 局部匹配
  • regex_replace -> 匹配后替换
    c++11 regex使用起来很方便简洁,代码如下:
///
//函数说明 :  pcre正则解析字符串
//参数说明 :  [linedata]  规则字符串
//           [cb_arg]   回调参数,返回捕获特定内容
//返回值   :  无
//作者     :  buding
//修改日期 :  2021-09-22
void * MatchStrFileName(std::string linedata, void *cb_arg)
{std::regex regex_rule("(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s(\\S+)");std::smatch cm;std::regex_match (linedata, cm , regex_rule);for(auto match_key: cm){std::cout << "match data: " << match_key << std::endl;}
}

打印结果如下:


正则支持对比

PCRE库对正则表达式基本都支持,但c++11 regex不支持逆序环视,这和Regex的流派有关,事实上每种语言的regex都不太相同,特别是逆序环视,对性能影响很大。即便对逆序环视支持的语言也对逆序的长度有限制,因此在使用(?<!*+{m,n})的时候要特别注意,尽可能避免。


性能对比

c++11 regex性能远不及pcre库的性能,但是在使用正则不是很频繁的时候使用c++11 regex更方便简洁,pcre库性能上确实很强劲,但是缺点就是代码书写起来冗余度很高。各个正则库性能比较链接里面已经做了详细的描述。

源代码

测试中所有源代码如下:

#include<iostream>
#include <string>
#include <vector>
#include <regex>
#include <pcre.h>
typedef void *(*Callback)(std::string,void *);bool PcreMatchCapture(char* pSubject, size_t nSubjectLen, const char* pPattern, int* pMatchVec, size_t nMatchVec, int& nMatchGroup)
{pcre* pPcre = NULL;const char* pError = NULL;int nErrorOffset = 0;pPcre = pcre_compile(pPattern, 0, &pError, &nErrorOffset, NULL);if (!pPcre){printf("[pcre] compile failed at offset %d: %s\n", nErrorOffset, pError);return false;}nMatchGroup = pcre_exec(pPcre, NULL, pSubject, nSubjectLen, 0, 0, pMatchVec, nMatchVec);if (nMatchGroup < 0){pcre_free(pPcre);return false;}pcre_free(pPcre);return true;
}void * MatchStrFileName(std::string linedata, void *cb_arg)
{int nMatchGroup = 0;int MatchVec[30] = {0};// 特殊符号'\'在程序中需要转义std::string regex = "(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s(\\S+)";if(PcreMatchCapture((char *)linedata.c_str(), linedata.size(), regex.c_str(), MatchVec, 30, nMatchGroup)){//字符串中有7组数据命中(特定字符组数 + 1)if(nMatchGroup == 7){std::string makefile(linedata.c_str()+MatchVec[2],MatchVec[3] - MatchVec[2]);printf("one hit data:%s\n", makefile.c_str());std::string auth(linedata.c_str()+MatchVec[4],MatchVec[5] - MatchVec[4]);printf("two hit data:%s\n", auth.c_str());std::string authfile(linedata.c_str()+MatchVec[6],MatchVec[7] - MatchVec[6]);printf("three hit data:%s\n", authfile.c_str());std::string gensigfile(linedata.c_str()+MatchVec[8],MatchVec[9] - MatchVec[8]);printf("four hit data:%s\n", gensigfile.c_str());std::string gensig(linedata.c_str()+MatchVec[10],MatchVec[11] - MatchVec[10]);printf("five hit data:%s\n", gensig.c_str());std::string licensefile(linedata.c_str()+MatchVec[12],MatchVec[13] - MatchVec[12]);printf("six hit data:%s\n", licensefile.c_str());}}
}bool ExecCommand(std::string lineData, Callback  cb, void * cb_arg)
{(*cb)(lineData,cb_arg);
}
int main()
{//cpp11 regex/*std::string regex_data = "Makefile auth auth.c gen_sig.c gensig license.lic";std::regex regex_rule("(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s(\\S+)");std::smatch cm;std::regex_match (regex_data, cm , regex_rule);//std::cout << regex_data << ": " << std::regex_match(regex_data, regex_rule) << std::endl;for(auto match_key: cm){std::cout << "match data: " << match_key << std::endl;}*///pcre regex/*std::string regex_data = "Makefile auth auth.c gen_sig.c gensig license.lic";std::vector<std::string> vecstr;ExecCommand(regex_data, MatchStrFileName, &vecstr);*/return 0;
}

c++11 regex 与 PCRE库使用相关推荐

  1. pcre库文件的安装

    PCRE是一个Prel库,包括perl兼容的正规表达式库,这些在执行正规表达模式匹配时用与Perl5同样的语法是很有用的.Boost太庞大了,使用boost regex后,程序的编译速度明显变慢测试了 ...

  2. c++11 regex 正则表达式验证车牌号

    在使用c++11 regex验证车牌号前,要首先明白有几个坑要踩: 1.车牌号校验规则,只有弄清楚了校验车牌号的规则才能写出正确的正则表达式,所以首先要弄清楚车牌号的校验规则. 2.c++11 中re ...

  3. C++11学习笔记-----线程库std::thread

    在以前,要想在C++程序中使用线程,需要调用操作系统提供的线程库,比如linux下的<pthread.h>.但毕竟是底层的C函数库,没有什么抽象封装可言,仅仅透露着一种简单,暴力美 C++ ...

  4. linux c 11 运行库,11.1.3 运行库与I/O

    11.1.3  运行库与I/O 在了解了glibc和MSVC的入口函数的基本思路之后,让我们来深入了解各个初始化部分的具体实现.但在具体了解初始化之前,我们要先了解一个重要的概念:I/O. IO(或I ...

  5. CodeBlocks使用第三方库(以使用pcre库为例)

    CodeBlocks使用第三方库 ----以使用pcre库为例                                                                     ...

  6. 《JavaScript权威指南第7版》第11章 JavaScript标准库

    第11章 JavaScript标准库 11.1 Set和Map 11.1.1 Set类 11.1.2 Map类 11.1.3 WeakMap和WeakSet 11.2 类型数组和二进制数据 11.2. ...

  7. C++11中的时间库std::chrono(引发关于时间的思考)

    文章目录 前言 chrono 的概况 chrono 的核心内容 duration clock system_clock steady_clock time point 关于时间的思考 时间函数思考 总 ...

  8. JavaScript权威指南 第11章JavaScript标准库

    JavaScript权威指南 第11章JavaScript标准库 第11章 JavaScript标准库 11.1 集合与映射 11.1.1 Set类 11.1.2 Map类 11.1.3 WeakMa ...

  9. ubuntu16.04安装PCRE库

    PCRE是一个轻量级的函数库,支持解析正则表达式,性能超过了POSIX正则表达式库和一些经典的正则表达式库. 为NGINX编写模块,需要用到此库,下面是Ubuntu16下PCRE库的安装与验证: 输入 ...

最新文章

  1. typora新增主题,typora将主题导入本地
  2. R语言设置或查询图形参数par函数
  3. instantclient_11_2 连接oracle数据
  4. flex布局的一点注意点
  5. 求两个数的公约数java_java中怎样求两个数的最大公约数?
  6. CentOS7安装Mono和MonoDevelop
  7. 【NOIP2017提高组】宝藏
  8. 黑苹果无线网卡选择intel还是博通?及其驱动方式详解
  9. 人事管理系统都有哪些功能和优势?
  10. java解析xml方法_详解Java解析XML的四种方法
  11. 2022年,教你跳过验证快速创建Google账户!
  12. 计算机科任学 排名,2018软科中国最好学科排名正式发布
  13. 致远OA 组合getshell
  14. 静态网页设计课后练习
  15. 在Windows下编写的代码,实时在Linux下编译
  16. 德语语法笔记——名词的变格
  17. 权限和归属——基本权限和特殊权限
  18. 关于Echarts折线图双Y轴网格的一些配置
  19. vr分类及其常见类型
  20. 1555:计算双阶乘

热门文章

  1. 提高准时交货率有哪些措施
  2. 数据处理的计算机语言,一种事务数据处理用计算机语言,COBOL (common business-oriented language),音标,读音,翻译,英文例句,英语词典...
  3. 【035】基于java的进销库存管理系统(Vue+Springboot+Mysql)前后端分离项目,附万字课设论文
  4. 微服务--数据一致性
  5. 蔡学镛:编译、反编译、反反编译
  6. ffmpeg 读取显示摄像头数据
  7. 达内linux运维课程,达内linux运维工程师
  8. 虚拟化(Citrix Netscaler)双因素身份认证解决方案
  9. libcurl中上传文件的坑-英文操作系统中文路径无法上传返回26错误码
  10. 响应式表格,表格自适应(responsive table)