常识性优化
1、避免重新编译
编译和定义正则表达式的次数应尽可能的少。
2、使用非捕获型括号
如果不需要引用括号内的文本,请使用非捕获型括号(?:...)。这样不但能节省捕获的时间,而且会减少回溯使用的状态的数量,从两方面提高速度。而且能够进一步的优化,例如消除务必要括号。
3、不要滥用括号
在需要的时候使用括号,在其他时候使用括号会阻止某些优化措施。除非你需要知道.*匹配的最后一个字符,否则请不要使用(.*)。
4、不要滥用字符组
例如 ^.*[:] 这样会付出处理字符组的代价,而实际上这个式子并需不要用到字符组提供的多字符匹配功能,我认为,当一个字符是元字符时例如 . 或 * 应该使用\.或\*表示,在比如需要 [Ff],应当使用不缺分大小写的匹配,而不是字符组。
5、使用起始锚点
除非是及其罕见的情况,否则以 .* 开头的正则表达式都应该在最前面添加 ^ 或者\A 如果这个正则表达式在某个字符串的开头不能匹配,那么显然在其他位置它也不能匹配。添加锚点无论是手工添加还是通过优化自动添加都能够配合开头字符/字符串/字串识别优化,节省大量不必要的工作。
将文本独立出来
1、从量词中提取必须的元素
用 xx* 替代 x+ 能够暴露必须匹配的 x 同样,用-----{0,2}代替-{5,7}。
2、提取多选结构开头的必须元素
用th(?:is|at)替代(?:this|that),就能暴露出必须的th。如果不同的多选分支的结尾部分相同,我们也可以从右面"提取"。例如(?:optim|standard)ization 。
将锚点独立出来
1、在表达式前面独立出 ^ 和 \G
^(?:abc|123)和(^abc|^123)在逻辑上是等价的,但是许多正则引擎指挥对第一个表达式使用开头字符/字符串/字串识别优化。所以第一种办法的效率高得多。
2、在表达式末尾独立出$
虽然 abc$|123$ 和 (?:abc|123)$ 在逻辑上是等价的,但优化的表现可能不同。目前只对Perl有效。