首发于 接触的触

std::regex && google::re2 杂谈

发现自己还没开始连载就断更了,总有点过意不去。不过总能给自己找点正当理由:

1.上上周周末出去约会了,没写,

2.上周周末出去约会了,没更。

程序员怎么可能有对象

跟了一个客户端版本需求,真兴奋。这大概是实习四个月以来第一次放养我自己看代码,找修改的地方,然后跟进需求,还要自己和客户端同学联调什么什么的。而且修改的地方范围之广也是这么久以来第一次。虽然最后差点没有赶上打包灰度,还是灰度的小哥哥硬生生等了我三个小时。不过想想还是很开心的。

虽然引发我差点没有提代码的元凶是老大没来得及批,但是,用来背锅的关键点就是这个垃圾正则表达式了。

首先作为一个c++程序员,现阶段最开心的事情就是用stl了。原装库,瞬间调用,加上std命名空间就能立刻跑起来。但是,同时作为一个google框架的受害(益)者,std库我们当然都是有第三方代码库完全覆盖的了啊。这就导致了一个很神奇的现象:

我:std::stoi
CODE READER:不不不,你改成StringToNumeric
我:std::future
CODE READER:不不不,你看一下第三方库里有个Feature类,你调用一下它

...然而,之前前面这些东西都是人来告诉我的。而这一次:

我:std::regex
GOOGLE STYLE:Overlaps with many regular expression libraries in Chromium. When in doubt, use re2.

别以为换了一个报错提示我就不敢喷了。那头老大在催我赶紧提代码,这头给我搞出个这么个东西。emmm,狼人杀真好玩,等狼人杀玩完了再说。结果玩完回来的时候就是20:30了。

不过好歹,这里有提示。std::regex不能用,那就是说就要用re2了。翻了一下第三方代码库,果然有这么个东西。不过怎么使用搞不来。在github上翻到有re2开源项目,真的开心。有开源肯定有wiki了。结果:

哈?welcome ***呢。当时就来了句经典的国骂。当然,因为时间比较紧就没有仔细看右边这牌导航栏。果然还是gayhub用的太少了,连账号都不登,还怎么看得见右边这一排

闲谈说完了,现在开始说正事。

zh.cppreference.com/w/c

首先我贴一个c++ regex的中文reference页面。话说我这个单词还真的不知道要怎么翻译

关于这个东西挺好理解的,默认大家就都会用了

能调用的函数也就三个:

  1. regex_match 完全匹配
  2. regex_search 部分匹配
  3. regex_replace 文本替换

一般用正则表达式在整个字符串匹配对应的模式串用regex_search比较多,regex_match,自认为用的不会很多。没事谁会在程序里跑个正则来assert当前值对不对啊。

blog.csdn.net/mycwq/art

然后再贴个blog,google搜索第一个,里面对在这三个函数的各种调用和调用结果写的都挺好的。很完整,阅读很舒服,我要写blog也要写成这个样子。(当然是不可能的啦,超懒的,“你要学会复用别人的结果 -- 冯诺依曼”)

接下来我要讲真的正经事了:GOOGLE::RE2

所有的中文blog对RE2的介绍都是从这句话开始的: RE2 是一个快速、安全和 线程友好 的C++正则表达式引擎。

妈耶,这么高大上的吗?吓得我赶紧翻阅了一下源代码。不过我要问一句,线程友好是个什么鬼?老哥们翻译英文页面都这么不走心的吗?

(源网页:https://github.com/google/re2/wiki/WhyRE2)
WhyRE2
Paul Wankadia edited this page on 23 Sep 2016 · 1 revision
Safety is RE2's raison d'être.
RE2 was designed and implemented with an explicit goal of being able to handle regular expressions from untrusted users without risk. One of its primary guarantees is that the match time is linear in the length of the input string. It was also written with production concerns in mind: the parser, the compiler and the execution engines limit their memory usage by working within a configurable budget – failing gracefully when exhausted – and they avoid stack overflow by eschewing recursion.
It is not a goal to be faster than all other engines under all circumstances. Although RE2 guarantees linear-time performance, the linear-time constant varies depending on the overhead entailed by safe handling of the regular expression. In a sense, RE2 behaves pessimistically whereas backtracking engines behave optimistically, so it can be outperformed in various situations.
It is also not a goal to implement all of the features offered by Perl, PCRE and other engines. As a matter of principle, RE2 does not support constructs for which only backtracking solutions are known to exist. Thus, backreferences and look-around assertions are not supported.
For more information, please refer to Russ Cox's articles on regular expression theory and praxis:
Regular Expression Matching Can Be Simple And Fast
Regular Expression Matching: the Virtual Machine Approach
Regular Expression Matching in the Wild

方便一点就把内容全部复制一下。这个RE2的目标是让用户无风险的处理没有保证的正则表达式。它的优点在于简单、快速、安全。它的快速来源于它的解析时间是线性可控的。而且不会有爆栈的风险。文尾附赠的文章里有提到,传统的标准分析器能支持很多特性,很多写法,支持很多不同的匹配方式。不过缺点在于运行速度。在匹配串到达一定长度之后,匹配的时间会指数级增长。而这里的RE2,匹配时间是根据匹配串的长度线性增长的,并且是可预期的。当然同时它舍弃了一些匹配模式。作为google style的受害(益)者,本着安全和高效的理念,固然RE2才是上选。

然后再标记一下RE2的语法。方便之后自己再用的时候找到。

RE2能用到的函数也只有四个:

RE2::FullMatch("hello", "h.*o");                            // 全匹配
RE2::PartialMatch("hello", "ell");                          // 部分匹配
RE2::Consume(&input, "(\\w+) = (\\d+)\n", &var, &value);    // 从头匹配(匹配字符串的开头匹配的部分)
RE2::FindAndConsume(&input, "(\\w+)", &word);               // 可以不从头匹配

也同样能定义模式串和匹配串

模式串:
RE2 pattern("h.*o"); 
string contents = ...;          // Fill string somehow
StringPiece input(contents);    // Wrap a StringPiece around it

不过这里的匹配串可能只是引用?反正原字符串被释放了之后就不能在用了。这点要注意一下

哦对了,不说还忘了,还有一个功能:

// Example:
//   const RE2::Arg* args[10];
//   int n;
//   // ... populate args with pointers to RE2::Arg values ...
//   // ... set n to the number of RE2::Arg objects ...