PCRE正则语法
PHP Manual

性能

模式中一些项可能比其他一些更加高效. 比如使用[aeiou]这样的字符类会比可选路径(a|e|i|o|u)高效. 一般而言, 用尽可能简单的构造描述需求是最搞笑的. Jeffrey Friedl书(精通正则表达式)中包含了很多关于正则表达式性能的讨论.

当一个模式以.*开始并且设置了PCRE_DOTALL选项时, 模式通过PCRE隐式锚定, 因为它可以匹配字符串的开始. 然而, 如果PCRE_DOTALL 没有设置, PCRE不能做这个优化, 因为.元字符不能匹配换行符, 如果目标字符串包含换行符, 模式可能会从一个换行符后面开始匹配, 而不是最开始位置. 比如, 模式(.*) second匹配目标字符串”first\nand second”(\n是一个换行符)第一个捕获子组结果是”and”. 为了这样做, PCRE尝试从目标字符串中每个换行符后开始匹配.

如果你使用模式匹配没有换行符的目标字符串, 可以通过设置PCRE_DOTALL或以^.*开始的模式明确指示锚定以获取最佳性能. 这样节省了PCRE沿目标字符串扫描查找换行符重新开始的时间.

小心模式中的无限重复嵌套. 这在应用到不匹配字符串时可能会导致运行时间很长. 考虑模式片段(a+)*

这个模式可以有33种方式匹配”aaaa”, 并且这个数字会随着字符串的长度的增加迅速增加. (*重复可以匹配0,1,2,3,4次, 并且除了0外每种情况+都有不同次数的匹配对应). 当模式的剩余部分导致整个匹配失败的时候, PCRE原则上回尝试每种可能的变化, 这将会非常耗时.

对于一些简单的情况的优化是像(a+)*b这样紧接着使用原文字符串.. 在着手正式匹配工作之前, PCRE检查目标字符串后面是否有”b”字符, 如果没有就立即失败. 然而当紧接着没有原文字符的时候这个优化是不可用的. 你可以比较观察(a+)*\d和上面模式的行为差异. 前者在应用到整行的”a”组成的字符串时几乎是立即报告失败, 而后者在目标字符串长于20个字符时, 时间消耗就相当可观.


PCRE正则语法
PHP Manual