[英]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}
。 $
(?=[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.