「正则表达式」六、正则表达式的构建(前端必懂 )

往期回顾

正文内容

正则的构建需要考虑以下几点的平衡:

  • 匹配预期的字符串
  • 不匹配非预期的字符串
  • 可读性和可维护性
  • 效率

我们还需要考虑这么几个问题:

  • 是否需要使用正则

如能使用其他 API 简单快速解决问题就不需要使用正则:

「正则表达式」六、正则表达式的构建(前端必懂 )

  • 是否需要使用复杂正则

/(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/

将这个正则拆分成多个小块,如下:

「正则表达式」六、正则表达式的构建(前端必懂 )

1. 准确性

即需要匹配到预期目标,且不匹配非预期的目标。

  • 匹配固定电话

如需要匹配下面固定电话号码,可以分别写出对应正则:

055188888888 => /^0\\d{2,3}[1-9]\\d{6,7}$/
0551-88888888 => /^0\\d{2,3}-[1-9]\\d{6,7}$/
(0551)88888888 => /^0\\d{2,3}-[1-9]\\d{6,7}$/

然后合并:

let r = /^0\\d{2,3}[1-9]\\d{6,7}$|^0\\d{2,3}-[1-9]\\d{6,7}$|^\\(0\\d{2,3}\\)[1-9]\\d{6,7}$/

然后提取公共部分:

let r = /^(0\\d{2,3}|0\\d{2,3}-|\\(0\\d{2,3}\\))[1-9]\\d{6,7}$/

再优化:

let r = /^(0\\d{2,3}-?|\\(0\\d{2,3}\\))[1-9]\\d{6,7}$/
  • 匹配浮点数

先确定,符号部分([+-])、整数部分(\\d+)和小数部分(\\.\\d+)。

「正则表达式」六、正则表达式的构建(前端必懂 )

整理后:

「正则表达式」六、正则表达式的构建(前端必懂 )

2. 效率

正则表达式运行过程:

  1. 编译
  2. 设定起始位置
  3. 尝试匹配
  4. 若匹配失败则返回前一步重新匹配
  5. 返回匹配成功失败的结果

我们常常优化对 3 和 4 步进行优化:

  • 使用具体字符组替代通配符,消除回溯

如 /"[^"]*"/ 代替 /".*?"/。

  • 使用非捕获型分组

当不需要使用分组引用和反向引用时,此时可以使用非捕获分组。

如 /^[-]?(?:\\d\\.\\d+|\\d+|\\.\\d+)$/ 代替 /^[-]?(\\d\\.\\d+|\\d+|\\.\\d+)$/。

  • 独立出确定字符

加快判断是否匹配失败,进而加快移位的速度。

如 /aa*/ 代替 /a+/。

  • 提取分支公共部分

减少匹配过程中可消除的重复。

如 /^(?:abc|def)/ 代替 /^abc|^def/。

  • 减少分支的数量,缩小它们的范围

如 /rea?d/ 代替 /red|read/。


分享到:


相關文章: