Java Regex需要太长时间

时间:2014-08-19 07:11:07

标签: java regex byte

我有这个正则表达式

"((\\s{0,2})\\p{XDigit}{2}\\s{0,2})*"

用户可以像这样从字节转储中选择匹配的字符串 enter image description here

上面的选择应该是可能的,但是选择Byte的一半不应该这样 enter image description here

结尾或开头的空格不应该是这样的问题 enter image description here

给定正则表达式的问题是匹配需要太长时间。我能改进什么,问题是什么?

编辑:

所以我为这个案例建立了一个解决方案。我唯一需要检查的是字符串的开头和结尾。删除空格并检查分割字符串的第一个和最后一个元素长度是否为1.我无论如何都要拆分它,因为之后我将它解析为一个字节数组。

        String selection = dumpText.getSelectionText();

        if (selection.equals(" ") || selection.equals("  ")){
            return;
        }

        //remove spaces at the beginning
        while(selection.charAt(0) == ' '){
            selection = selection.substring(1);
        }

        //remove spaces at the end
        while(selection.charAt(selection.length()-1) == ' '){
            selection = selection.substring(0, selection.length()-1);
        }

        String[] splitted = selection.split("\\s{1,2}");

        if(splitted.length == 0 || splitted[0].length()==1 || splitted[splitted.length-1].length()==1){
                return;
        }

4 个答案:

答案 0 :(得分:3)

当你问一些简单的事情时,基本的字符串比较会更有效率。在这种情况下,您只对前2个和后2个字符感兴趣。

所以你只能测试那些(在验证长度之后):

s.charAt(0) != ' ' && s.charAt(1) == ' ' 
    && s.charAt(s.length - 1) != ' ' && s.charAt(s.length - 2) == ' '

虽然这不是很花哨,但它会非常快。你只是测试你是否有一个角色然后是一个空格,最后是另一种方式。

这仅适用于基本验证。

答案 1 :(得分:1)

尝试这种模式:

\s{0,2}(?:\p{XDigit}{2}\s{0,2})*

您遇到Catastrophic Backtracking,其中(在这种情况下)您有多种方法无法匹配字符串。
我写的模式基本相同,但应该只有一种方法匹配选择:

  • \s{0,2} - 可选的前导空格
  • (?:\p{XDigit}{2}\s{0,2})* - 一个或多个十六进制对,后面有空格。

请注意,此模式可以匹配没有空格的十六进制数字,例如12AB,但它仍适用于您的用例。

答案 2 :(得分:0)

另一个解决方案,只是检查是否有任何单个字符被空格包围。

/^([a-zA-Z0-9]\s+)|(\s+[a-zA-Z0-9]\s+)|(\s+[a-zA-Z0-9])$/gm

或类似的东西,以便在序列的开头或结尾匹配单个字符

/^([a-zA-Z0-9]\s+)|(\s+[a-zA-Z0-9])$/gm

或者这个,它只返回两个字符出现

/(?:\s*)([a-zA-Z0-9]{2})(?:\s*)/gm

Demo 1 | Demo | Demo 3

附注:在这种情况下,您可以使用\p{XDigit}代替[a-za-z0-9]

答案 3 :(得分:0)

我实际上并不会尝试匹配前置空格或尾随空格,并且会使正则表达式像使用单词边界一样简单

\\b\\p{XDigit}{2}\\b

Matcher#find中使用此正则表达式可以单独匹配每个字节序列。

- RegEx Demo