高性能的正则表达式效率优化

作者:小菜 更新时间:2025-02-26 点击数:
简介:前言编写高性能的正则表达式,有如下几条规则,这几条规则是本人总结出来的:1、使用正确的边界匹配器(^、$、\b、\B等)2、使用具体的元字符、字符类(\d、\w

【菜科解读】

前言

编写高性能的正则表达式,有如下几条规则,这几条规则是本人总结出来的:

1、使用正确的边界匹配器(^、$、\b、\B等)

2、使用具体的元字符、字符类(\d、\w、\s等)

3、使用正确的量词(+、*、?、{n,m})

4、使用非捕获组、原子组

5、注意量词的嵌套

其实正则表达式的很多优化技巧都是围绕着“减少回溯”这样一个原则进行优化的。

至于什么是“回溯”,笔者就不在这里重复了,以下通过具体的例子理解这样的过程。

示例

一、以下是一则匹配电子邮件地址的正则表达式:

^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$

先一步步的解析:

1、^\w+:表示必须以字符开始, 且是一个或者多个;

2、([\.-]?\w+)*中的“[\.-]?”表示匹配“.”或者“-”,零次或者一次;

3、([\.-]?\w+)*中的“\w+”则表示匹配一个或者多个的字符;

4、([\.-]?\w+)*整个则表示匹配.xxx、-xxx或者xxx这样的字符,且零次或者多次;

5、第1-4步,则匹配sunny或者sunny.yang这样的字符;

6、“@”则是具体元,匹配具体的@;

7、 \w+:则表示匹配的一个或者多个的字符,因为email不可能这样嘛:sunny@.gmail.com;

8、([\.-]?\w+)*:则跟第2-4步一样,匹配.163、-lib、.gd这样的字符,且零次或者多次;

9、(\.\w{2,3})+$:则匹配.com、.cc这样结尾的域名,且因为\w{2,3}限定了长度必须为2-3位,所以不能匹配.c、.n这样的字符。

乍看这样一个解析过程没问题,逻辑正确,但其实暗藏很多问题,看看以下的一个匹配图,backtrack则表示回溯(使用RegexBuddy可以很清晰的看到这过程)

整个成功的匹配过程经历了55步,我们先分析下整个匹配过程:

1、图中的第1和2步,匹配^\w+,匹配成功,匹配了“admin”;

2、图中第3步,匹配[\.-]?,当然由于不存在“.”和“-”,因此没匹配上具体的字符,但又由于“?”的限定,可以匹配零或者一次,因此这个子表达式匹配成功,虽然没匹配上具体的字符。

3、图中第4步,匹配\w+,由于“+”限定一个或者多个以上字符,但后续已经没[a-zA-Z0-9]可以匹配了,因此产生回溯,回溯到上次匹配成功的位置,也就admin;

4、图中第5步,因为上一步产生了回溯,所以“[\.-]?\w+”匹配了零次,由于([\.-]?\w+)*中限定零次或者多次,因此也匹配成功,也没匹配上具体的字符;

以下步骤,匹配该过程:

^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$

5、图中第6步,匹配了“@” ,第7步匹配了“\w+”,即匹配了“open”;

6、图中第8-13步,匹配“([\.-]?\w+)*” ,匹配了“-lib”、“.com”,匹配“.com”可能与我们期望不相符,我们期望这子表达式匹配的是www.xx.gd.cn中的“.gd”;

7、图中第7-10步,匹配了open-lib,第7-13步则匹配了open-lib.com;

8、因为“([\.-]?\w+)*”中的量词是“*”,则继续重复这个过程;

9、 图中第14步,匹配“([\.-]?\w+)*”中的“[\.-]?”,因为此时指针已经位于@open-lib.com之后了,但由于量词“?”,因此也匹配成功,但没匹配上字符,也没字符可匹配;

10、 图中第15步,匹配“([\.-]?\w+)*”中的“\w+”,此时指针仍位于字符串末尾,没任何字符能匹配,所以匹配失败,产生回溯,回到上次成功的位置,即图中的第13步,继续下个表达式的匹配;

11、 图中第16步,匹配(\.\w{2,3})+中的“\.”,由于没有任何字符能匹配,匹配失败,进行回溯;

12、图中第17步 ,(\.\w{2,3})+中量词“+”,表示该表达式必须匹配一次或者多次,由于上一步匹配失败了,所以匹配零次,但不符合一次或者多次的限定,因此继续回溯;

13、由于上一步匹配失败,需要进行回溯,因此表达式没有更多的分支了,只能将指针回退一个字符,回溯上次成功的位置,即([\.-]?\w+)*中\w+的位置(这是上次产生分支的位置);

14、图中剩下的步骤,就重复着匹配([\.-]?\w+)*,回退字符,匹配(\.\w{2,3})+这样的过程,直到匹配成功。

二、以下看看另外一则同样匹配邮件地址的正则表达式:

^\w+([-\.]\w+)*@\w+([-\.]\w+)*\.\w+([-\.]\w+)*$

这个正则跟上面的看起来貌似差不多,不过细看还是有区别的,也先一步步来解析:

1、^\w+:表示必须以字符开始, 且是一个或者多个(这一步与上面的一样);

2、([-\.]\w+)*中的“[-\.]”表示匹配“-”或者“.”;

3、([-\.]\w+)*中的“\w+”则表示匹配一个或者多个的字符;

4、([-\.]\w+)*整个则表示匹配.xxx、-xxx这样的字符,且零次或者多次;

5、第1-4步,则匹配sunny或者sunny.yang这样的字符;

6、“@”则是具体元,匹配具体的“@”;

7、 \w+:则表示匹配的一个或者多个的字符,因为email不可能这样嘛:sunny@.gmail.com;

8、([-\.]\w+)*:则跟第2-4步一样,匹配.163、-lib、.gd这样的字符,且零次或者多次;

9、“\.”则是具体元,匹配“.”;

10、\w+:则匹配一个或者多个字符;

11、([-\.]\w+)*:则匹配“.com”、“-lib”、“.c”这样的字符,且可以零次或者多次;

12、$:则表示结尾

乍看这个正则的步骤过程貌似比上一则长,其实不然,同时这个正则也存在着问题,先看看匹配图,同样backtrack表示回溯:

对的,你没看错,整个正确的匹配过程用了19步,对比前面的55步,简直天与地的差别。

,我们继续分析下匹配过程:

1、图中的第1和2步,匹配^\w+,匹配成功,匹配了“admin”;

2、图中第3步,匹配[-\.],当然由于不存在“.”和“-”,因此没匹配上具体的字符,也没具体的量词允许匹配零次,所以不用继续往下匹配了,因此直接产生了回溯;

3、图中第4步,因为上一步产生了回溯,所以“[-\.]\w+”匹配了零次,由于([-\.]\w+)*中限定零次或者多次,因此也匹配成功,也没匹配上具体的字符;

以下步骤,匹配该过程:

^\w+([-\.]\w+)*@\w+([-\.]\w+)*\.\w+([-\.]\w+)*$

4、图中第6步\w+,匹配了open;

5、图中第7-12步匹配([-\.]\w+)*,匹配了“-lib”和“.com”;

6、因为“([-\.]\w+)*”中的量词是“*”,则继续重复这个过程;

7、图第13步,匹配([-\.]\w+)*,因为此时指针已经位于@open-lib.com之后了,也没具体的量词允许匹配零次,因此匹配失败,回溯到上次成功的位置;

8、图第14步,匹配([-\.]\w+)*$中的“[-\.]”,此时指针仍位于字符串末尾,没任何字符能匹配,所以匹配失败,产生回溯,回到上次成功且还没尝试过的位置,即图中的第9步;

9、经过上面的回溯,指针已经位于@open-lib之后的位置了;

10、图第15步匹配了“.”,第16步\w+则匹配了“com” ;

11、图第17步匹配([-\.]\w+)*,由于此时指针又位于字符串末尾,因此[-\.]部分没匹配上任何字符,因此产生回溯;

12、图第18步,由于([-\.]\w+)*的量词是“*”,表示匹配零次或多次,虽然子表达式[-\.]匹配失败,所以整个表达式匹配了零次,也是匹配成功;

13、最后一步第19步,“$”表示末尾匹配,因为此时指针位于字符串末尾,故符合,因此也匹配成功。

分析

整个匹配过程关键优化地方,还是回溯,两个示例表达式看起来相近,匹配过程也部分类似,但两个例子的效率却如此大的分别,现在来分析一下造成回溯的原因。

对比下两个表达式不同的部分:

^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$

^\w+([\.-]\w+)*@\w+([\.-]\w+)*\.\w+([-\.]\w+)*$

高性能,的,正则,表达式,效率,优化,前言,编写,

和珅被抓的时候,刘墉出了力没有?他正在做什么

公元1799年,中枢大臣被捕。

这一消息传出,造成的震撼,绝不亚于在不久前去世的消息。

此时在朝中长期担任内阁大学士的,又在做什么呢? 刘墉跟和珅之间的关系,一直是民间戏说常用的题材。

刘墉被塑造成一个睿智、清廉,敢于跟大贪官和珅作斗争的形象。

而在真实历史中,又有一些不同。

和珅跟刘墉,这两位都是乾隆时期非常重要的大臣。

他们两个之间有很多相似的地方。

刘墉跟和珅的家庭,都是官宦人家。

和珅的父亲曾任福建副都统,属于正二品官员。

刘墉的父亲级别更高,曾担任过军机大臣、内阁大学士的职位。

军机大臣掌握实权,内阁大学士官居一品。

这两个职位在都有“宰相”的称呼。

不过,和珅是满洲正红旗出身。

在乾隆时期,八旗官员会比汉人官员地位更高。

所以,他们两个人的起点,其实相差不大。

刘墉后来得以踏上仕途,更多是依靠自己的本事。

他在考试中,顺利考证进士。

后来又入选庶吉士。

翰林院在清朝时位置特殊。

一直有“非进士不得入翰林,非翰林不得入内阁”的说法。

刘墉得以入翰林院,将来也就有机会入阁拜相。

和珅则是靠父辈的荫封,才获得官职。

不过,他们两人在年轻时,也各自受到了不小的挫折。

和珅的父亲去世后,他在家族里就没了地位。

如果不是靠着一位老家丁和偏房亲戚的庇佑,和珅在家族里的生存都会非常艰难。

想要获得官职,更是机会渺茫,更是很难有后来的显赫声势。

刘墉遇到的麻烦,也是来自受他父亲的牵连。

刘墉父亲因为办事失误,被皇帝送进监狱。

不过,刘墉情况稍好,他的父亲没过多久就被从监狱里释放出来,并很快重新授予重任。

在踏上仕途后,两人却有很大不同。

和珅都是长期在中枢机构办事。

像一开始担任的侍卫,级别虽然不高,却距离皇帝较近,可以被了解,得到更快的提拔任用。

刘墉虽然有调任中枢,但长期在地方任职。

皇帝对他的印象,主要来自地绩。

乾隆中前期的阶段,刘墉的政绩一直不错,并且在地方上的名声极佳。

甚至百姓还将刘墉视为“包公再世”。

但是,到乾隆后期,刘墉的名声愈差,经常出现办错事情的情况。

这段时期的乾隆皇帝,愈加,对旁人的建议,大多无法听进去。

对乾隆的劝谏,也被乾隆当面斥责。

同一时间段,和珅倍受重用。

不可否认,和珅确实是一个能力极强的官员。

而且,他更懂得迎合皇帝,讨乾隆开心。

所以,和珅从领班大学士、军机大臣到九门提督等,兼任数十个职位。

而刘墉只是勉强授了一个体仁阁大学士的职位。

虽然这个职位也有宰相的地位。

但乾隆一直不愿授予刘墉。

乾隆授予刘墉体仁阁大学士的时候是在二年。

而在嘉庆元年提拔官员时,原本有资历名望入选的刘墉,却被排除在外。

乾隆让刘墉担任大学士的时候,还抱怨,自己是因为没有人选,才会提拔他。

但是,又过了两年,也就是嘉庆四年的时候,形势发生逆转。

乾隆皇帝驾崩,改朝换代的时候到了。

和珅虽然兼任几十个职位,但是真的跟掰手腕的时候,完全不是对手。

更何况,嘉庆还使了手腕。

他让和珅负责乾隆丧事,把他跟其他人隔离开,然后,一举拿下。

这种情况下,其实和珅仍有一丝机会。

毕竟他是朝廷中枢大员,皇帝要杀他,也需要足够证据。

毕竟和珅深耕官场多年,党羽众多。

而在这种情况下,刘墉主动为嘉庆送上和珅的罪状。

刘墉为和珅查明罗列的罪状非常详细,从横征暴敛,到搜刮民脂民膏等20多项罪名。

招招毙命。

刘墉的奏疏递上去后不久,和珅就被赐死。

而在这以后,刘墉就重新开始展现他的才能了。

乾隆中后期以来,各处积弊极深。

许多问题已经到了不整治,就可能断送江山的地步。

可是,乾隆后期,言路闭塞,很多人根本不敢说话。

只是一味地阿谀奉承。

刘墉在和珅被处死后,就递了一封奏疏,专门讲如何处理漕运积弊的事情。

漕运是负责为京城运送粮食的,来往利益极大,腐败也非常严重。

不过,刘墉的这道奏疏,并没有得到太多实际的推行。

因为这种积弊,已经无法靠一两个人就可以根除的情况。

但刘墉依然得到嘉庆皇帝重用,甚至在嘉庆离开京城,到热河行宫时,把北京的事情都交给刘墉负责。

而刘墉也一直工作在嘉庆九年,也就是乾隆跟和珅去世5年后才去世,享年85岁。

随机文章台风战斗机性能参数详解,成本6000万欧元可外挂13枚导弹曝光中国异能人士公开,生活在我们身边的异能人士(电人/万磁王)世界上最后一条美人鱼,距今1万多年历史(美人鱼真实存在过)科学另类解读时间之谜,宇宙时间并不存在毁掉你的科学认知一个看似普通的水塘,潜到30米下,发现了神奇的“地狱之钟”

聊一聊,2025年农村社保卡的报销比例是多少钱?看看你的可以报销不?(2025年4月21日)

农村社保卡在医院里能报多少,但这篇指南将为你提供一步到位的方法,让你轻松完成报销。

下面随新社通小编一起了解详情。

农村社保卡报销比例最新的具体内容是什么农村社保卡报销的比例是多少?第1点:大病补偿此外,对于大病补偿,镇风险基金会有一定的补偿。

例如,一次性或全年累计应报医疗费超过5000元以上,会有分段补偿。

然而,需要注意的是,有些费用并不在报销范围内,如自行就医(未指定医院就医或不办理转诊单)、自购药品、公费医疗不能报销的药品和不符合计划生育的医疗费用等。

农村社保卡的报销比例和范围是根据具体的医疗情况和就医机构来定的。

农村社保卡报销的比例是多少?第2点:住院补偿镇卫生院报销比例为60%。

二级医院报销比例为40%。

三级医院报销比例为30%。

农村社保卡报销的比例是多少?第3点:农村社保卡能报销的医疗费用,主要取决于就医的机构级别以及所产生的医疗费用类型。

门诊补偿在村卫生室及村中心卫生室就诊,可报销60%,每次就诊处方药费限额为10元,卫生院医生临时补液处方药费限额为50元。

在镇卫生院就诊,可报销40%,每次就诊各项检查费及手术费限额为50元,处方药费限额为100元。

在二级医院就诊,可报销30%,每次就诊各项检查费及手术费限额为50元,处方药费限额为200元。

在三级医院就诊,可报销20%,每次就诊各项检查费及手术费限额为50元,处方药费限额为200元。

加入收藏
               

高性能的正则表达式效率优化

点击下载文档

格式为doc格式

八大菜系 22 2025-04
  • 账号登录
社交账号登录