Java Matcher慢速正则表达式
这是一个非常简单的正则表达式,它在一个非常短的字符串上运行超过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]结尾
# 1 楼答案
我认为从你所说的,你的正则表达式可以简化为这个
编辑-(为子孙后代)在阅读了@Holger的帖子后,我改变了这个选项,以修复可能发生的灾难性回溯,并加速回溯,正如我的长椅所示,这可能是最快的方法
# 2 楼答案
我试图猜测你的意图,但并不容易:
(?=[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
方法,则不需要前导^
或尾随$
;它已经暗示字符串边界必须与表达式边界匹配我希望我没有弄错你的意图
# 3 楼答案
--
,只需使用负的前瞻(?!.*--)
李>{1}
也没有意义李>(?=[a-z0-9-]{1,63}$)
末尾添加$
李>所以也许
^(?=[a-z0-9-]{1,63}$)(?!.*--)[a-z0-9-]+[a-z0-9]$
# 4 楼答案
我已经修复了这个正则表达式,如下所示:
第
([a-z0-9]+[-]{0,1}){1,63}
节变成:([a-z0-9]{0,1}|[-]{0,1}){1,63}