js 正则学习小记之匹配字符串字面量优化篇

 更新时间:2020年04月08日 22:20:39   作者:楼教主  
昨天在《js 正则学习小记之匹配字符串字面量》谈到 /"(?:\\.|[^"])*"/ 是个不错的表达式,因为可以满足我们的要求,所以这个表达式可用,但不一定是最好的

昨天在《js 正则学习小记之匹配字符串字面量》谈到 /"(?:\\.|[^"])*"/ 是个不错的表达式,因为可以满足我们的要求,所以这个表达式可用,但不一定是最好的。
从性能上来说,他非常糟糕,为什么这么说呢,因为 传统型NFA引擎 遇到分支是从左往右匹配的,
所以它会用 \\. 去匹配每一个字符,发现不对后才用 [^"] 去匹配。
比如这样一个字符串: "123456\'78\"90"
16 个字符,除了第一个 " 直接匹配成功,还剩余 15 个,只有 2 个转义(4 个字符),所以 \\. 会失败 10 次,只有 2 次成功。
10 次匹配失败,需要回溯后用 [^"] 才能匹配成功,当然最后一个 " 会直接匹配成功。

很明显,正常的字符串不可能全是转义,正常的字符串才是主流,当然不排除有人故意全转义的情况。
所以这个正则需要10次回溯后才能匹配完成,如果字符串增长到 1K 1M 肿么破呢?
所以我们要修改下这个正则,前后换下位置么?
难道是 /"(?:[^"]|\\.)*"/ ? 呵呵,好像不太对,这样的话转义就不能被匹配了。

所以还要修改下 /"(?:[^"\\]|\\.)*"/ 这样就OK了,遇到 \ 转义就会用 \\. 去尝试匹配。

可是还是有问题,因为我们在 [^"\\] 过滤掉了 \n 所以没法匹配多行字符的情况。

js 中 字符串用 \ 折行是允许的,但是修改后的 正则 没法匹配这样的字符串了,所以我们还得继续修复。

因为 . 没法匹配换行,所以我们要用其他方式表达。
. 是用于匹配除换行符之外的所有字符,难道我们要 [.\n] 来表示么?
这样是不对的,因为 [] 字符集中的 . 不再表示除换行符之外的所有字符,而是字符 . 也就是他本身一个字符而已。
那怎么办呢?
其实换个思路,
\d 表示 0-9
\D 表示 [^0-9]
那么 [\d\D] 就表示所有了,不是么。(新人朋友不知道能不能消化这个知识点。)
同理 [\s\S] [\w\W] 同样可以。
所以 /"(?:[^"\\]|\\[\d\D])*"/ 这样就满足我们的要求了。

效果不错。
回头过来分分析下他现在的性能吧。
还是这个字符串: "123456\'78\"90" , 正则 /"(?:[^"\\]|\\[\d\D])*"/

16 个字符,除了第一个 " 直接匹配成功,还剩余 15 个,有 2 个转义(4 个字符),[^"\\] 能匹配成功 10 个字符,只有 2 次失败。
为什么不是 4 次失败呢,明明有4个字符啊。\\ 虽然是2个字符,但是读到第一个 \ 就匹配失败,然后用 \\[\d\D] 匹配成功,
占用掉了两个字符 \\ 下次用下一个o开始匹配,所以只有2次回溯。

只有 2 次需要回溯,然后用 \\[\d\D] 匹配成功。当然最后一个 " 还是会直接匹配成功。
所以从 10 次回溯,减少到了 2 次,虽然正则比昨天臃肿了很多,但至少性能提升了不止一个等级。

OK,今天的分享完毕,明天见。

相关文章

  • swift中的正则表达式小结

    swift中的正则表达式小结

    正则表达式是对字符串操作的一种逻辑公式,用事先定义好的一些特定字符、及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑。
    2015-10-10
  • [php]正则表达式的五个成功习惯

    [php]正则表达式的五个成功习惯

    [php]正则表达式的五个成功习惯...
    2007-03-03
  • 正则表达式(regular)知识(整理)

    正则表达式(regular)知识(整理)

    正则(regular),要使用正则表达式需要导入Python中的re(regular正则的缩写)模块。下面通过本文给大家介绍正则表达式(regular)的相关知识,感兴趣的朋友一起学习吧
    2017-05-05
  • 使用正则表达式屏蔽关键字的方法

    使用正则表达式屏蔽关键字的方法

    关键字屏蔽是社交类软件必做的功能,当我们熟悉正则的时候,我们完全用正则来过滤掉用户输入的空格,而且用正则可以过滤掉任意位置的空格,具体正则屏蔽关键字的方法大家可以参考下本文
    2017-07-07
  • 用正则查找html中有id属性的html标签

    用正则查找html中有id属性的html标签

    查找html中有id属性的标签,说具体点就是尖括号中还有id=""的html标签
    2012-10-10
  • 让editplus3 函数模板完全显示函数

    让editplus3 函数模板完全显示函数

    我是常常使用editplus ,主要是它启动快,文件小,自定义代码,绿色。发现当用他打开php有一个快捷键ctrl+F11可以打开函数列表,也就是文件内所有的函数名会显示在列表中,双击会选中函数,非常方便
    2012-10-10
  • 正则表达式.号元字符(除了回车符\r和换行符\n)

    正则表达式.号元字符(除了回车符\r和换行符\n)

    这篇文章主要介绍了正则表达式.号元字符(除了回车符\r和换行符\n),需要的朋友可以参考下
    2016-12-12
  • 利用正则表达式将字符串分组示例代码

    利用正则表达式将字符串分组示例代码

    这篇文章主要给大家介绍了关于利用正则表达式将字符串分组的相关资料,文中分别介绍了利用itertools模块的groupby()方法和利用正则表达式是如何实现的,通过示例代码介绍的非常详细,需要的朋友们下面来一起看看吧。
    2017-08-08
  • python 正则表达式 re.sub & re.subn

    python 正则表达式 re.sub & re.subn

    正则表达式一个比较常见的用途是找到所有模式匹配的字符串并用不同的字符串来替换它们。sub方法提供一个替换值,可以是字符串或函数,和一个要被处理的字符串。这篇文章主要介绍了python 正则表达式 re.sub & re.subn,需要的朋友可以参考下
    2017-12-12
  • 正则表达式检测用户输入的email地址是否合法

    正则表达式检测用户输入的email地址是否合法

    在注册系统开发中,需要检测用户输入的email地址是否合法,都可以使用正则表达式来检测,下面有个小例子,希望对大家有所帮助
    2014-01-01

最新评论