CC++中正则表达式库RE2的使⽤
RE2是Google开源的正则表达式库,RE2是多语⾔⽀持的,提供对C/C++,Python,Ruby等,本⽂介绍C语⾔的RE2的正则库。正则表达式在⼯程实践中是⾮常有⽤的,可⽤于信息提取,内容⽐对,替换等。
c++中string的用法安装
主要步骤,下载安装包,解压,编译,安装。需要说明的是较新版本源码添加了对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<int>(strlen(str))) { }
StringPiece(const std::string& str): ptr_(str.data()), length_(static_cast<int>(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;";
string regmail = "(\\w+([-+.]\\w+)*)@(\\w+([-.]\\w+)*)\\.(\\w+([-.]\\w+)*)";
re2::RE2::Extract(content.c_str(),*pHandle,"\\0,\\1,\\3,\\5",&strVal);
strVal的值为"test@gmail,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表⽰只能从star 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<<group[i]<<";";
}
cout<<endl;
}
上述的正则表达式包含两个⼦表达式,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<bool, const StringPiece&, const RE2&, Arg, RE2::FullMatchN> FullMa
tch;
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对象中,然后在每次调⽤时重⽤这个对象。如:
RE2re("(\\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<<content<<endl; //"please visit 127.0.0.1:8999 master:8088 here"只有第⼀个匹配结果被替换
}
content = "please visit localhost:8999 or master:8088 here";
cout<<"relapce count:"<<RE2::GlobalReplace(&content, re, "127.0.0.1:\\2")<<endl; //"2",即有两处被替换
out<<content<<endl; //"please visit 127.0.0.1:8999 or 127.0.0.1:8088 here"所有匹配结果都被替换
Demo
// g++ -g testRE2.cpp -o run -lre2
#include <iostream>
#include <string>
#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<<pHandle->error()<<endl;
return -1;
}
string content = "test,regular,邮件 test@gmail; ";
string strVal ;
if(re2::RE2::Extract(content.c_str(),*pHandle,"\\0,\\1,\\3,\\5",&strVal))
{
cout<<strVal<<endl;
}
if(pHandle != NULL)
{
delete pHandle;
pHandle = NULL;
}
}
{
StringPiece group[3];
RE2 re("(\\w+):([0-9]+)");
string content = "please visit localhost:8999 here";
if(re.Match(content,0,content.size(),RE2::UNANCHORED,group,3))
{
for(size_t i = 0; i < 3 ;++i)
{
cout<<group[i]<<";";
}
cout<<endl;
}
}
{
string host;
int port;
string content = "please visit localhost:8999 here";
RE2::FullMatch("localhost:8999","(\\w+):([0-9]+)",&host,&port);
cout<<host<<":"<<port<<endl;
RE2 re("(\\w+):([0-9]+)");
RE2::FullMatch("master:8088", re, &host, &port);
cout<<host<<":"<<port<<endl;
}
{
RE2 re("(\\w+):([0-9]+)");
string content = "please visit localhost:8999 here";
if(RE2::Replace(&content, re, "127.0.0.1"))
{
cout<<content<<endl;
}
content = "please visit localhost:8999 or master:8088 here";
cout<<"relapce count:"<<GlobalReplace(&content, re, "127.0.0.1")<<endl;
cout<<content<<endl;
}
return0;
}
本⽂简介了使⽤C/C++语⾔操作RE2库的主要⽅法,⾄于正则表达式的语法详见RE2的参考⽂档。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。