繁体   English   中英

Java Matcher慢速正则表达式

[英]Java Matcher slow regex

这是一个非常简单的正则表达式,它在一个非常短的字符串上运行了30秒钟以上:( i7 3970k @ 3.4ghz

Pattern compile = Pattern.compile("^(?=[a-z0-9-]{1,63})([a-z0-9]+[-]{0,1}){1,63}[a-z0-9]{1}$");
Matcher matcher = compile.matcher("test-metareg-rw40lntknahvpseba32cßáàâåäæç.nl");
boolean matches = matcher.matches(); //Takes 30+ seconds

第一部分(?=)是断言字符串最多包含这些字符

第二部分是断言,例如在这种情况下字符串不会超出语法,以防止使用-并至少在[a-z0-9]中结束

我试图猜测你的意图,但这并不容易:

(?=[a-z0-9-]{1,63})这种前瞻性似乎要求下一个最多63个字符为小写ASCII字母或数字,但实际上,即使有只有一个字母后跟任何东西。 因此,也许您的意思是(?=[a-z0-9-]{1,63}$)禁止使用不超过63个字符的合法字符。

您似乎想要在-之间添加至少一个字母或数字的组,但您使-可选项的目的并不是真正地创建约束,而是允许产生很多可能性的方式,从而增加了表达式的开销。 您可以简单地说: ([a-z0-9]++-){0,63}[a-z0-9]+ 花括号中的组至少需要一个字母或数字,之后需要减号,结尾处的表达式在表达式末尾至少需要一个字母或数字,但也将匹配最后一个没有后缀的组-同时。 如果没有-则最后一组可能也是唯一的一组-完全包含在您的文本中。

将所有正则表达式放在一起将成为: (?=[a-z0-9-]{1,63}$)([a-z0-9]++-){0,63}[a-z0-9]+ 注意,如果使用matches方法,则不需要前导^或尾随$ 它已经暗示字符串边界必须匹配表达式边界。

我希望我的意图是对的...

我已修复此正则表达式,将其替换如下:

^(?=[a-z0-9-]{1,63})([a-z0-9]{0,1}|[-]{0,1}){1,63}[a-z0-9]{1}$

([a-z0-9]+[-]{0,1}){1,63}变为: ([a-z0-9]{0,1}|[-]{0,1}){1,63}

  • 如果要确保没有--在字符串中,请使用否定的前瞻(?!.*--)
  • 也没有必要写{1}
  • 另一件事是,如果要确保字符串最多包含63个字符,则在预读中需要在末尾添加$ (?=[a-z0-9-]{1,63}$)

因此,也许^(?=[a-z0-9-]{1,63}$)(?!.*--)[a-z0-9-]+[a-z0-9]$

我认为从您所说的内容来看,您的正则表达式可以简化为
编辑-(供后人使用)阅读@Holger的帖子后,我将其更改为修复可能的灾难性回溯并加快其执行速度,正如我的工作台所显示的那样,这可能是最快的方法。

 #  ^(?=[a-z0-9-]{1,63}$)[a-z0-9]++(?:-[a-z0-9]+)*+$

 ^                                    # BOL
 (?= [a-z0-9-]{1,63} $ )              # max 1 - 63 of these characters
 [a-z0-9]++ (?: - [a-z0-9]+ )*+       # consume the characters in this order
 $                                    # EOL

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM