正则表达式—优化

**##正则表达式匹配过程##

序号 过程 解释
1 编译 检查表达式语法正确性,若正确则编译成内部形式
2 开始传动 将引擎放置到字符串开始的位置
3 监测元素 引擎开始测试表达式和文本中的各个元素:1-依次尝试相连元素,直到失败;2-量词,控制权在量词(是否继续匹配)和被限定元素(是否匹配)之间轮换;3-控制权,括号用于捕获,在进入和退出括号时需要开销来修改引擎状态。
4 寻找匹配结果 NFA会获取已经匹配的结果而停止引擎,POSIX NFA会一直匹配所有可能,并获取匹配成功的最长的文本
5 驱动 如果找不到匹配,驱动引擎到文本下一个位置,开始新的尝试
6 彻底失败 从开始到最后全部尝试失败则失败

一、优化传动

1、优化字符串起始点/行锚点
(1)任何以^开头的表达式必须能够匹配,引擎才会开始工作,所以识别^是必须的
(2)^a|^b通常情况下难以确定其实,^(a|b)或者^(?:a|b)可以更快匹配
2、优化字符串结束/行锚点
(1)表达式以$或其他结尾锚点来结尾时候,可以从字符串末尾倒数若干字符的位置开始尝试匹配,这样会节省很多时间
3、开头字符/字符组/子串识别优化
使用特定的字符或文字子串,通过传动装置更快更准确地定位匹配的开始位置,如 the|them|other,只能从文本中ot的位置开始匹配。

二、优化表达式本身

1、化简量词优化
约束普通元素的加号、星号之类的量词,避免引擎大部分逐步处理的开销,比如 .*(?:.)*是逻辑相同,但速度不同的两个表达式,因为 .*会作为一个整体来考虑,省去了括号和量词之间控制权之间的转移所消耗的时间。
2、消除没有必要的括号
3、消除没有必要的字符组,比如[a],单个字符构成的字符组没有直接字符a快
4、忽略优先量词(.*?等)的匹配速度往往比匹配优先量词要慢,尤其当忽略优先量词在捕获型括号内时候。如果字符串很短,差别不明显;如果字符串很长,比如 ^.*:^.*?:,如果:靠近开头位置,用忽略优先量词比较快,如果在末尾位置用匹配优先量词。
5、使用固化分组和占有优先量词(?<……)来削减备用状态
6、量词等价交换。\d\d\d和\d{3}效果相同,效率后者更高
7、提取多选结构开头的必须元素:用 the(?:e|em|re)代替 (?:the|them|there)非常有价值,因为可以更快定位“the”
8、模拟开头字符串识别
(?=[JFMASOND])(?:Jan|Feb|…|Dec)更快速定位月份,`JFMASOND就是各个月份首字符

三、消除循环

1、什么是循环
所谓循环就是多选结构当中的星号所引起的多次来回匹配。
2、如何解决?
<1>取出多选结构中真正匹配成功的子表达式,按待会提到模式去构建
<2>自顶而下,根据经验和匹配要求通过假设进行构建
3、消除循环通常模式
模式: open nomal*(special nomal*)*closing
举例:
<1>匹配包括转义引号字符串
- 文本:”he said \”hi there\” and left”
- 表达式: "[^\\"]*(\\.[^\\"]*)*"
–**解析:**nomal是 [^\\"]+
—————special是 \\.
<2>匹配多字符串
- 文本: i
- 表达式: (?>[^<]*)(?>(?!)<[^<]*)*
–**解析:**nomal是 [^<]*
—————special是
【需要注意的事项】
(1)special和nomal开头不同
(2)nomal必须至少匹配一个字符串
(3)special部分必须是固化的,即文本不能由该部分的多次迭代完成。**

你可能感兴趣的:(正则表达式)