有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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]结尾


共 (4) 个答案

  1. # 1 楼答案

    我认为从你所说的,你的正则表达式可以简化为这个
    编辑-(为子孙后代)在阅读了@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
    
  2. # 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. # 3 楼答案

    • 如果你想确保你的字符串中没有--,只需使用负的前瞻(?!.*--)
    • 同样,写{1}也没有意义
    • 另一件事是,如果您想确保字符串最多包含63个字符,那么在展望中,您需要在(?=[a-z0-9-]{1,63}$)末尾添加$

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

  4. # 4 楼答案

    我已经修复了这个正则表达式,如下所示:

    ^(?=[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}