【问题标题】:Very slow Regular Expression in JavaJava中非常慢的正则表达式
【发布时间】:2021-11-25 19:52:30
【问题描述】:

使用 Java,我想检测一行是否以单词和分隔符开头,然后是“myword”,但是这个正则表达式花费的时间太长。哪里不对?

^\s*(\w+(\s|/|&|-)*)*myword

【问题讨论】:

  • 你说的耗时太长是什么意思?图案太长?还是需要很长时间才能返回带有特定输入的结果?
  • 对于这个例子“DEPUIS JUILLET 2011 Consultant Montreal”,它不会在 60 秒以下返回任何结果
  • 你需要String rx = "^\\s*(\\w+(?:[\\s/&-]+\\w+)*)[\\s/&-]+myword";,检查ideone.com/CT4ENA
  • 谢谢它的工作,但为什么这个更有效?

标签: java regex


【解决方案1】:

模式^\s*(\w+(\s|/|&|-)*)*myword 由于嵌套量词而效率不高。 \w+ 至少需要一个单词字符,(\s|/|&|-)* 可以匹配零个或多个某些字符。当* 应用于组并且输入字符串在单词字符之间没有分隔符时,表达式变得类似于经典catastrophical backtracking issue 模式的(\w+)* 模式。

只是\w+(\w+)* 性能的一个小插图:

\w+:                                              (\w+)*

你的模式更复杂,涉及更多的回溯步骤。为避免此类问题,模式不应在量化组内具有可选子模式。也就是说,使用强制子模式创建一个组并将必要的量词应用于该组。

在这种情况下,您可以展开您拥有的组

String rx = "^\\s*(\\w+(?:[\\s/&-]+\\w+)*)[\\s/&-]+myword";

IDEONE demo

在这里,(\w+(\s|/|&|-)*)* 展开为 (\w+(?:[\s/&-]+\w+)*)(我保留了外括号以生成捕获组 #1,如果您对它们不感兴趣,可以删除这些括号)。 \w+ 匹配一个或多个单词字符(因此,它是一个强制性子模式),(?:[\s/&-]+\w+)* 子模式匹配零个或多个(*,因此,这整个组是可选的)来自定义字符类[\s/&-]+(因此,它是强制性的)后跟一个或多个单词字符\w+

【讨论】:

    猜你喜欢
    • 2020-06-21
    • 2014-05-04
    • 2018-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多