书写高效的正则表达式,正则表达式性能优化方法

影响 NFA 类正则表达式(常见语言:GNU Emacs,Java,ergp,less,more,.NET语言,PCRE library,Perl,PHP,Python,Ruby,sed,vi ) 其实主要是它的“回溯”,减少“回溯”次数(减少循环查找同一个字符次数),是提高性能的主要方法。

演示

示例

源字符串:<script type="text/javascript">adsfadfsdasfsdafdsfsadfsa</script>
匹配要求:匹配 <script….>….</script> 标签里面所有内容,包括改标签

方法 1

因为 <script 后面可能出现字符、空白、特殊符号等,还有标签里面也可能出现各种 js 代码。

我们简单方法是,正则表达式:<script.*?>.*?</script> (测试工具使用了:regexBuddy)

总共花费 115 步,回溯了:48 次。 因为我们使用 . 字符,匹配默认情况下除了 \n 之外所有字符。

方法 2

我们分析特点发现,<script…> 后面,应该是除了 > 之外都可以字符,然后一对 <script> 标签里面 js 内容。可以定义为除了 < 之外。 正则表达式:<script[^?>]+>[^<]+</script>

19 步,0 次回溯! ,步骤只有原先的 15 %左右,性能几倍的提升了!从上面我们看到,不同正则表达式,对通用字符配平,性能相差会很大。减少“回溯”是最好的方法,减少回溯其中最主要的方法是:”用最小范围的元字符,尽量避免用过大的元字符!”。

一般规律如下:

  • 使用正确的边界匹配器(^、$、\b、\B等),限定搜索字符串位置
  • 使用具体的元字符、字符类(\d、\w、\s等) ,少用”.”字符
  • 使用正确的量词(+、*、?、{n,m}),如果能够限定长度,匹配最佳
  • 使用非捕获组、原子组,减少没有必要的字匹配捕获用(?:)

如:我想匹配一些英文字母,它后面接的是数字,如:abc1234。我可以写 \w+\d+,也可以写 [a-zA-Z]+\d+ ,其中第一个 \w+ 会先匹配所有 abc1234,然后回溯,匹配满足 \d+ 格式,一共4步,而后面这个只需要 2 步,步骤减少一半了!

相关推荐

正则表达式匹配原理与解析过程探讨分析

正则表达式匹配原理与解析过程探讨分析

已经有多篇关于正则表达式介绍的文章,随着我们越来越多使用正则表达式,想对性能做优化、减少我们正则表达式书写匹配 Bug。我们不得不进一步深入了解正则表达式执行过程了。下面我们一起学习,分析下正则表达式执行过程。 我们会用 regexbuddy 测试工具分解执行过程,具体工具使用,可以看:正则表达式性能测试工具推荐、 ...

正则表达式的修正符:i、g、m、s、x、e

正则表达式的修正符:i、g、m、s、x、e

正则表达式中常用的模式修正符有 i、g、m、s、x、e等。它们之间可以组合搭配使用。 它们的作用如下: 修正符:i 不区分大小写的匹,如: /abc/i 可以与 abc 或 aBC 或 ABc 等匹配。 修正符:g 表示全局匹配 修正符:m 将字符串视为多行,不管是那行都能匹配。例,模式为:$mode="/abc/m"; ,要匹配的字符串为:$str="bcefg5 ...

正则表达式中需要转义的特殊字符

正则表达式中需要转义的特殊字符

如果要查找文件名中有*的文件,则需要对*进行转义,即在其前加一个\。ls \*.txt。正则表达式有以下特殊字符。 $ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n' 或 ‘\r'。要匹配 $ 字符本身,请使用 \$。 ( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要 ...

微信扫一扫,分享到朋友圈

书写高效的正则表达式,正则表达式性能优化方法