正则表达式是一项昂贵的操作吗?至少看起来
Posted
技术标签:
【中文标题】正则表达式是一项昂贵的操作吗?至少看起来【英文标题】:Is regex a costly operation? It seems atleast 【发布时间】:2016-04-13 00:14:45 【问题描述】:我正在为字符串编写正则表达式模式。字符串是常量类型/结构。我的意思是,它看起来像(这个格式不是那么重要,看下一个例子)-
[Data Code Format]: POP N/N/N (N: object): JSON object data
这里的 N 代表一个数字或数字。 [ ] 里面是一组字符串块。但是,这种格式是不变的。
所以,我写了一个正则表达式-
\s*((?:\S+\s+)1\S+)\s*(?:\((?:.*?)\))?:\s*(\S*)\s*(\w+)
记住这个字符串示例-
%DATA-4-JSON: POP 0/1/0 (1: object): JSON object data
效果很好,但是,我在regex101.com 上看到的是成功匹配。但是,它经历了 330 个步骤来实现这一目标。
截图-
我的问题是,它需要 330 步来实现这一点(至少在我看来,我觉得它相当沉重),我想这可以使用 if-else
和其他步骤较少的比较来实现?
我的意思是,正则表达式字符串解析这么重吗?我需要解析的 10000 个字符串的 330 步会很重,对吧?
【问题讨论】:
默认情况下任何东西都只匹配一次。 “昂贵”与什么相比? 200 美元贵吗? 写得不好的正则表达式模式不仅成本高昂,而且很危险。这个有太多可以匹配空字符串的子模式。因此,回溯陷入其中并失败,然后重试并失败......这会使您的模式变得昂贵。 是的,正则表达式很昂贵,所以要明智地使用它。 @bozzmob 编写一个没有正则表达式的函数并比较两者。如果它需要快速,那么尝试几种解决方案通常是一个好主意。浏览器有分析工具(按 F12),您可以使用它来测量它。 【参考方案1】:当您使用正则表达式时,如果您使用回溯,它们的成本可能会很高。当您使用带有可能相互匹配的后续模式的量词时(并且如果它们之间的模式可能匹配空字符串(通常用*
、0,x
或?
量词声明)),回溯可能会起到一个坏把戏在你身上。
你的正则表达式有什么不好?
一个轻微的性能问题是由不必要的非捕获组(?:\S+\s+)1
引起的。它可以写成\S+\s+
,它已经减少了步数(a bit, 302 steps)。然而,最糟糕的是\S
匹配:
分隔符。因此,正则表达式引擎必须尝试许多可能的路线来匹配您预期匹配的开头。将 \S+\s+\S
替换为 [^:\s]+\s+[^:\s]+
和 step amount will decrease to 159!
现在,来到 (?:\((?:.*?)\))?
- 删除不必要的内部非捕获组会带来另一个轻微的改进 (148 steps),用否定字符类替换 .*?
会带来另一个提升 (139 steps)。
我现在就用这个:
\s*([^:\s]+\s+[^:\s]+)\s*(?:\([^()]*\))?:\s*(\S*)\s*(\w+)
如果最初的 \s*
是强制性的,那将是另一个增强功能,但您会有不同的匹配项。
【讨论】:
+1 以获得关于“如何优化”和“有什么问题”的清晰解释!这正是我想要的。以上是关于正则表达式是一项昂贵的操作吗?至少看起来的主要内容,如果未能解决你的问题,请参考以下文章