昨天晚上看
《深入浅出正则表达式》,看到对于正则式效率一节,好奇测试了一下。
平时写正则式,只求能达到目的就好了,从来没想过效率这问题(顶多就是不需要的分组不捕获),昨天一测试,吓我一跳
用一下里面的例子,写一个正则式,检测的字串中的每个字段间用逗号做分隔符,第12个字段由P开头
1,2,3,4,5,6,7,8,9,10,11,12,13
写法一 匹配次数
(.*?,){11}p
120628次
^(.*?,){11}p
60400次
(\w*?,){11}p 1485次
^(\w*?,){11}p 170次
^([^,\r\n]*,){11}P 133次
注:正则式不是很准确,只是为了说明效率问题
解决方案:
一种简单的方案是尽可能的使匹配精确。用取反字符集代替点号。例如我们用如下正则表达式
^([^,\r\n]*,){11}P,这样可以使失败回溯的次数下降到11次。
另一种方案是使用原子组。
(测试了一下,JS不支持,C#和JAVA是支持的)
原子组的目的是使正则引擎失败的更快一点。因此可以有效的阻止海量回溯。原子组的语法是
(?>正则表达式)。位于(?>)之间的所有正则表达式都会被认为是一个单一的正则符号。一旦匹配失败,引擎将会回溯到原子组前面的正则表达式部分。前面的例子用原子组可以表达成
^(?>(.*?,){11})P。一旦第十二个字段匹配失败,引擎回溯到原子组前面的^。