如何掌握正则表达式这一开发利器,看这篇就够了( 四 )


(a*)* <=> (a+)* <=> (a*)+ <=> a*(a+)+ <=> a+5.2 使用非捕获组NFA 正则引擎中的括号主要有两个作用:

  1. 主流功能 , 提升括号中内容的运算优先级
  2. 反向引用
反向引用这个功能很强大 , 强大的代价是消耗性能 。所以 , 当我们如果不需要用到括号反向引用的功能时 , 我们应该尽量使用非捕获组 , 也就是:
// 捕获组与非捕获组() => (?:)5.3 分支优化分支也是导致正则回溯的重要原因 , 所以 , 针对正则分支 , 我们也需要作出必要的优化 。
5.3.1 减少分支数量首先 , 需要减少分支数量 。比如不少正则在匹配 http 和 https 的时候喜欢写成:
/^http|https/其实上面完全可以优化成:
/^https?/这样就能减少没必要的分支回溯
5.3.2 缩小分支内的内容缩小分支中的内容也是很有必要的 , 例如我们需要匹配 this 和 that  , 我们也许会写成:
/this|that/但上面其实完全可以优化成
/th(?:is|at)/有人可能认为以上没啥区别 , 实践出真知 , 让我们用以上两个正则表达式去匹配一下 that 。
如何掌握正则表达式这一开发利器,看这篇就够了

文章插图
 

如何掌握正则表达式这一开发利器,看这篇就够了

文章插图
 
我们会发现第一个正则的执行步骤比第一个正则多两步 , 那是因为第一个正则的回溯路径比第二个正则的回溯路径更长了 , 最终导致执行步骤变长 。
5.4 锚点优化在能使用锚点的情况下尽量使用锚点 。大部分正则引擎会在编译阶段做些额外分析, 判断是否存在成功匹配必须的字符或者字符串 。类似^、$ 这类锚点匹配能给正则引擎更多的优化信息 。
例如正则表达式 hello(hi)?$ 在匹配过程中只可能从字符串末尾倒数第 7 个字符开始, 所以正则引擎能够分析跳到那个位置, 略过目标字符串中许多可能的字符, 大大提升匹配速度 。
6. 结语曾经有一次因为写一个性能恶劣的正则表达式 , 导致代码执行过程因为性能问题挂掉 。于是下定决心要把正则表达式搞明白 , 看了不少文章书籍 , 做了不少练习之后 , 总算摸到了些门道 , 也真真切切体会到正则表达式的优美和强大 。写下此文 , 记录下一些学习心得和总结 , 望批评指正 , 共同进步 。




推荐阅读