学写提高性能的代码之字符串处理-3

160 阅读3分钟

这是我参与8月更文挑战的第13天,活动详情查看: 8月更文挑战

前言

通过对正则表达式原理及可能存在回溯失控场景的详细介绍,下面介绍在编写正则表达式时,有哪些方法和原则能够有效提升正则表达式的匹配效率。

优化正则表达式

  • 化繁为简:不要觉得将所有关于字符串处理的工作,放在一个正则表达式中完成是多自豪的事情,实践经验证明,很大规模的单一正则表达式很难维护,并且容易出现回溯失控的问题。所以在遇到需要处理许多任务的场景时,可使用
    条件逻辑将复杂的字符串搜索问题拆分为多个正则表达式来解决。
  • 将正则表达式赋值给变量:这样在重用正则表达式时,能避免对他们的重新编译。
  • 合适的量词:贪婪量词和惰性量词在正则表达式匹配过程中存在较大差异,使用合适的量词类型能有效地提升性能。
  • 更快失败:通常正则表达式执行较慢不是其匹配成功较慢,而是匹配失败的过程较慢。因为在使用正则表达式对一大段字符串中的一小部分进行匹配时,其中匹配失败的地方要比匹配成功的地方多得多,所以若想让正则表达式更快的执行完毕,应加快其失败的过程。
  • 尽量具体:对于子表达式能够重叠匹配或字符串与字元相邻时,正则表达式的可能分支路径会增加,为了避免这种情况,应使表达式更加具体化,比如说能用[^”\s\n]时就不要使用.
  • 减少分支数量:在正则表达式中,使用类似按位或的竖线符号|来表示分支选项,但通常建议尽量减少分支的使用,可以使用字符集或选项数组来代替,因为字符集在切换选项时使用的是位向量的方式,这比分支采用的回溯快。
  • 注意采用非捕获组:由于捕获组需要记录反向引用,它会更加消耗内存和引用,所以如果使用场景中不需要使用反向引用,则可以用非捕获组来避免多余的内存及时间开销。比如可以使用(?:pattern)代替(pattern)
  • 使用反向引用避免后处理:如果使用场景时需要引用匹配的一部分,则应尽量用捕获组捕获目标片段,然后通过反向引用进一步处理,而不是剥离出目标字符串后再手动处理。
  • 切忌弄巧成拙:在小心使用正则表达式处理复杂字符串操作时,其执行速度会非常快,但并非任何字符串处理使用正则表达式都是高效的,如果我们事先知道所要处理的字符位置,那么有些JavaScipt的原生方法在性能上会更加高效,比如字符串的charAt方法、slice方法及substr方法。另外如果要查找特定字符串的位置,或者判断其是否存在,lastIndexOf方法和indexOf方法会更适合。