博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C/C++中正则表达式库RE2的使用
阅读量:2425 次
发布时间:2019-05-10

本文共 4710 字,大约阅读时间需要 15 分钟。

RE2是Google开源的正则表达式库,RE2是多语言支持的,提供对C/C++,Python,Ruby等,本文介绍C语言的RE2的正则库。正则表达式在工程实践中是非常有用的,可用于信息提取,内容比对,替换等。

安装

主要步骤,下载安装包,解压,编译,安装。需要说明的是较新版本源码添加了对C++11的支持,同时也需要较高版本g++的支持,本文选择tag为re2-2016-02-01的较低版本。

类简介

使用RE2首先要构造正则表达式对象,RE2的构造函数如下:

RE2(const StringPiece& pattern);RE2(const StringPiece& pattern, const Options& option);

其中StringPiece是RE2提供的一个string风格的对象,在RE2构造函数中传入”const char*” 或者”string”对象时,将被隐式的转换为StringPiece对象。使用StringPiece可以减少”const char*”到”string”之间的来来回回的转换。StringPiece包含一个指向原始输入的指针,和一个字符串的长度计数,构造函数如下:

class StringPiece {private:    const char*   ptr_;    int           length_;public:    StringPiece() : ptr_(NULL), length_(0) { }    StringPiece(const char* str): ptr_(str), length_((str == NULL) ? 0 : static_cast
(strlen(str))) { } StringPiece(const std::string& str): ptr_(str.data()), length_(static_cast
(str.size())) { } StringPiece(const char* offset, int len) : ptr_(offset), length_(len) { } ...};

Options:构造函数中的Options,用于改变默认的设置,它是一个枚举类型,枚举值为:

  • DefaultOptions ,默认
  • Latin1, //将输入当做Latin-1(ISO-8859-1)编码,默认为UTF-8
  • POSIX, // POSIX语法,即从左开始最长匹配
  • Quiet // 不要输出正则表达式编译的错误等

    RE2类的其他方法:

//返回RE2对象是否被正确的创建bool ok() const { return error_code() == NoError; }//如果RE2对象没有被正确的创建,将返回相关的错误描述const string& error() const { return *error_; }

使用

下面介绍使用正则表达式提取结果的方法
1.Extract

/* *用于从text内容中,根据正则表达式提取内容 *text:待提取的内容 *pattern:构造,编译后的正则表达式 *rewrite:控制输出结果 *out:按照rewrite定义的输出结构 */static bool Extract(const StringPiece &text, const RE2& pattern, const StringPiece &rewrite, string *out);text:待提取的内容pattern:构造,编译后的正则表达式rewrite:控制输出结果out:按照rewrite定义的输出结构

这里重点说下rewrite,它用于控制输出结果,如果正则表达式含有多个字表达式,那么rewrite可以控制输出哪些匹配结果,它通常是’[digits]’,其中\0表示完整的匹配结果,而\1则表示第一个字表达式。例如:表达式regmail中含有多个字表达式,下面分别用\1,\3,\5分别输出邮箱的用户名,用户名等。

string content = "test,regular,邮件 test@gmail.com;";string regmail = "(\\w+([-+.]\\w+)*)@(\\w+([-.]\\w+)*)\\.(\\w+([-.]\\w+)*)";re2::RE2::Extract(content.c_str(),*pHandle,"\\0,\\1,\\3,\\5",&strVal);strVal的值为"test@gmail.com,test,gmail,com" //分隔符','是在rewrite中定义的符号

2.Match

bool Match(const StringPiece& text,int startpos, int endpos, Anchor anchor, StringPiece *match, int nmatch) const;text:待匹配的文本startpos:从text中进行匹配的开始位置endpos:从text中进行匹配的结束位置anchor:匹配的模式,Anchor是一个枚举类型,其值分别为:UNANCHORED表示从startpos到endpos之间任何位置开始匹配,ANCHOR_START表示只能从startpos开始匹配, ANCHOR_BOTH表示模式必须完全匹配startpos到endpos之间的字符串。match:它通常是是一个StringPiece数组,用于保存匹配结果nmatch:匹配的字段个数,通常nmatch值越小,匹配速度越快,应该避免使得nmatch>1+match数组的长度

下面介绍Anchor类型对匹配结果的影响:

StringPiece group[3];RE2 re("(\\w+):([0-9]+)");string content = "please visit 127.0.0.1:8999 here";if(re.Match(content,0,content.size(),RE2::UNANCHORED,group,3)){    for(size_t i = 0; i < 3 ;++i)    {        cout<
<<";"; } cout<

上述的正则表达式包含两个子表达式,group[0]是完整的匹配结果,group[1],group[2]分别输出模式”(\w+)”和”([0-9]+)”的结果,其输出如下:localhost:8999;localhost;8999;

如果将匹配模式改为:

re.Match(content,0,content.size(),RE2::ANCHOR_START,group,3);

那么只能匹配content值为”127.0.0.1:8999 here”,ANCHOR_START指明模式必须从startpos就开始匹配。

而如果将匹配模式改为:

re.Match(content,0,content.size(),RE2::ANCHOR_BOTH,group,3);

那么只能匹配content值为”127.0.0.1:8999”,ANCHOR_BOTH指明模式必须从startpos到endpos之间完全匹配。

3.FullMatch

static bool FullMatchN(const StringPiece& text, const RE2& re,const Arg* const args[], int argc);static const VariadicFunction2
FullMatch;

FullMatch通过模板VariadicFunction2,支持可变参数,将要提取的表达式,通过FullMatchN函数实现。使用:

string content = "please visit localhost:8999 here";string host;int port;RE2::FullMatch("local:8999","(\\w+):([0-9]+)",&host,&port);

匹配模式中含有两个子表达式,其值分别通过变量host和port进行提取。使用RE2::FullMatch(“local:8999”,”(\w+):([0-9]+)”,&host,&port);形式调用FullMatch,每次调用的时编译一次正则表达式,如果多次使用同一个匹配模式,这样会造成很多不必要的开销。可以编译一次正则表达式,保存到一个RE2对象中,然后在每次调用时重用这个对象。如:

RE2 re("(\\w+):([0-9]+)");RE2::FullMatch("master:8088", re, &host, &port);

4.Replace & GlobalReplace

static bool Replace(string *str, const RE2& pattern, const StringPiece& rewrite);static int GlobalReplace(string *str, const RE2& pattern, const StringPiece& rewrite);str:待替换的原始字符串,注意这一个指针,所有如果有匹配结果,将会直接修改原始数据;pattern:匹配的模式,即正则表达式rewrite:替换的模式,可以带有'\[digits]'表示的子模式结果

两者都可以用于替换,区别在于前只替换第一个匹配的结果,后者则会匹配所有匹配结果。关于返回值:前者返回是否替换成功(最多只会替换一次),后者返回全局整体被成功替换的次数。如下:

RE2 re("(\\w+):([0-9]+)");string content = "please visit localhost:8999 master:8088 here";if(RE2::Replace(&content, re, "127.0.0.1:\\2")){    cout<
<

Demo

// g++ -g testRE2.cpp -o run -lre2#include 
#include
#include "re2/re2.h"using namespace std;using namespace re2;int main(){ { string regmail = "(\\w+([-+.]\\w+)*)@(\\w+([-.]\\w+)*)\\.(\\w+([-.]\\w+)*)"; RE2 *pHandle = NULL; pHandle = new RE2(regmail, re2::RE2::Quiet); if( !pHandle->ok() ) { cout<
error()<

本文简介了使用C/C++语言操作RE2库的主要方法,至于正则表达式的语法详见RE2的参考文档。

转载地址:http://bkbmb.baihongyu.com/

你可能感兴趣的文章
程序员有话说 |当那个不靠谱的程序员跟我做同一个项目时
查看>>
怎样以程序员的方式来用百度呢?
查看>>
程序员是如何运用增长思维找到女朋友?
查看>>
@程序员,离职让企业损失近900亿,还遭疯抢!他凭什么?
查看>>
如何用 Python 一键查房价?
查看>>
累死累活干不过写 PPT 的?新东方年会吐槽视频俞敏洪不罚反奖 12 万!
查看>>
“离开360时,它只给了我一块钱”
查看>>
PDF 翻译神器,再也不担心读不懂英文 Paper 了
查看>>
漫话:如何给女朋友解释什么是RPC
查看>>
@程序员,为什么别人比你优秀?!
查看>>
你的红包狂欢夜,互联网巨头们的流量争夺战
查看>>
春晚过去 4 天了,你卸载百度 APP 了吗?
查看>>
中国移动互联网十年
查看>>
面试官问:请拿出一段体现你水平的代码,我该如何回答?
查看>>
@程序员,沟通这项核心技能你掌握了多少?
查看>>
2019,九问联想贺志强
查看>>
你可以忍受大城市 365 天的孤独,却不能忍受小城市 7 天的热闹
查看>>
35 岁程序员,年后第一天被辞退
查看>>
情人节她说:是的,嫁人当嫁程序员
查看>>
骚操作!代码写情诗 | 程序员有话说
查看>>