正则表达式重复子模式前、后倾的性能比较

在准备内部的正则表达式 (Regular Expression)分享的过程中, 注意到一个细节问题:重复的子模式,是应该前倾还是后倾,这两者在性能上有什么差异?

前倾和后倾是我胡诌的两个词,我的定义如下:

\n前倾\n 就是前面的子表达式使用贪婪匹配或较大的量词,尽可能多的匹配内容, 导致前面匹配的内容较多而使“天平”前倾。例如:/(?:\d{1,3}\.){3}\d{1,3}/
\n后倾\n 则相反,后面的子表达式使用贪婪匹配或较大的量词。如:/\d{1,3}(?:\.\d{1,3}){3}/

 

前倾和后倾在实际应用中很常见,如时间,主机名等,中间以某特殊字符(串?)分隔, 被分隔部分的规则又相同的情况下,一般都是使用这两种实现方式之一。

上面定义中的两个例子只是简例,可以用来大致匹配 IPv4 地址,完整的 IPv4 地址正则式如下, 它要求每段都在 0\n255 之间: 前倾:

/^(?:(?:[0\n9]|[1\n9][0\n9]|1[0\n9]{2}|2[0\n4][0\n9]|25[0\n5])\.){3}(?:[0\n9]|[1\n9][0\n9]|1[0\n9]{2}|2[0\n4][0\n9]|25[0\n5])\n/

后倾:

/^(?:[0\n9]|[1\n9][0\n9]|1[0\n9]{2}|2[0\n4][0\n9]|25[0\n5])(?:\.(?:[0\n9]|[1\n9][0\n9]|1[0\n9]{2}|2[0\n4][0\n9]|25[0\n5])){3}\n/

我写了一个测试比较这两个正则性能 的页面,在 IE7, FF3.6, Safari 4, Opera 10 下测试均为前倾的性能较高,Chrome 4 下则不相伯仲。

p.s. 这种重复子模式,要有语法上的简写就好了,像 Perl 正则的递归引用(或类似运行时反向引用), 维护起来就方便多了。