不同语言中有不同实现和限制,因此下面一些原则只是最基本的原则,不保证在所有实现中通用。有时候,有一种实现会对预知的情况进行优化,而另一种则不会。也就是说,正则表达式的效率不仅和正则引擎的种类相关,还和引擎具体实现有关。
1、使用字符组代替分支条件。
比如,使用[a-d]表示a~d之间的字母,而不是使用(a|b|c|d)。
2、优先选择最左端的匹配结果。
这在介绍分支条件匹配邮编的时候已经提到过。对于传统型NFA引擎来说,这样改动对正则匹配的效果是有利的,因为引擎一旦找到匹配结果就会停下来,而不会去尝试正则表达式的每一种可能(PHP中的preg函数就属于传统型NFA引擎)。
3、标准量词是匹配优先的。
若用量词约束某个表达式,那么在匹配成功前,进行的尝试次数有下限和上限。
4、谨慎用点元符号,尽可能不用星号和加好这样的任意量词。
只要能确定范围(例如“\w”),就不要用点号;只要能够预测重复次数,就不要用任意量词。
5、尽量使用字符串函数处理代替。
使用字符串函数和正则表达式都可以处理字符串,两者相比,字符串函数处理的效率更高。当然,有些情况几乎是非正则表达式不能胜任的,或者不用正则表达式的成本太高,这些情况不得不用正则表达式,既然如此,就应该设计好。
6、合理使用括号。
每使用一个普通括号(),而不是非捕获型括号(?:...),就会保留一部分内存等着再次访问。这样的正则表达式、无限次的运行次数,无异于一根根稻草的堆加,终将把骆驼压死。
7、起始、行描点优化。
能 确定起始位置,使用^能提高匹配的速度。同理,使用$标记结尾,正则引擎则会从符合条件的长度处开始匹配,略过目标字符串中许多可能的字符。在写正则表达 式时,应该将描点独立出来,例如”^(?:abc|123)比^123|abc“效率高,而”^(abc)比(^abc)"效率更高。
这个原则不适用于所有正则引擎。比如在PCRE中,二者效率相当。
8、量词等价转换的效率差异。
例如在PHP中,使用“\d\d\d”和“\d{3}”,或者“====”和“={4}”,他们之间的效率几乎没有差别。但是换用其他语言可能就会有比较明显性能差异了。
9、对大而全的表达式进行拆分。
10、使用正则以外的解决方案。
前 面已经提到,在有的场合可以使用字符串来代替正则表达式,此外,还有其他方案可以代替正则表达式。例如,在某项目中需要分析PHP代码,分离出对应的函数 调用(以及源代码对应的位置)。虽然这是用正则表达式也可以使用,但无论从效率还是代码复杂度方面考虑,这都不是最优的方式。PHP已经内置解析器的接口 PHP Tokenizer。
使用PHPTokenizer能简单、高效、准确地分析出PHP源代码的组成。token_get_all函 数参数为一段PHP代码,可提取出这段代码里的常量、变量、类名、函数等。这在编写phpdoc、代码优化提速、自动加载类时都可以用到。比如,在解析 URL时没必要用正则表达式,使用parse_url函数即可;在获取HTTP头时,也可以使用get_headers函数。
这里总结几种正则表达式的取代方案,他们能部分取代正则表达式的实现。
PHP的字符串函数;
PHP的Tokenizer系列函数;
PHP的url函数及一些http函数;
PHP的filter系列函数;
JavaScript的DOM模型。
以上内容,摘自《PHP核心技术与最佳实践》——正则表达式相关章节,加深自己对正则表达式的理解与应用,在这里分享给大家。
由 PHP乐知博客 提供