模式匹配时冻结

时间:2013-09-24 20:53:21

标签: java regex

我的程序遇到了一个小问题。它似乎冻结了,很可能是由while循环引起的。

我想要做的就是拿起并替换Java评论。因此,在输入块注释时,您将使用/*打开该注释。如果没有结束结束(*/),程序将冻结5-6秒,您无法使用它。我已经运行了更多的正则表达式和一个超过10,000行的文件,没有性能问题,因此任何类型的性能下降都令人担忧,但仅有5秒的延迟。

private static final String COMMENT_MATCHER = "(//.*)|(/\\u002A((\\s)|(.))*?\\u002A/)";

private String clearMatches(String code, final String regex) {
    final Pattern pattern = Pattern.compile(regex);
    final Matcher matcher = pattern.matcher(code);
    while (matcher.find()) {
        final String match = matcher.group();
        code = code.replace(match, CharBuffer.allocate(match.length()).toString());
    }
    return code;
}

我猜测问题在于它找到许多匹配并迭代所有匹配,因为有一个迷路星号。

此致,Obicere。

2 个答案:

答案 0 :(得分:4)

试试这个:

COMMENT_MATCHER = "//[^\r\n]*+|/[*](?:(?![*]/)[\\s\\S])*+[*]/";

应该跑得快得多。

快速分解模式:


//                  # match "//"
[^\r\n]*+           # possessively match any chars other than line break chars
|                   # OR  
/[*]                # match "/*"
(?:                 # start non-capture group
  (?![*]/)[\\s\\S]  #   match any char, only if "*/" is not ahead
)*+                 # end non-capture group and possessively repeat zero or more times
[*]/                # match "*/"

答案 1 :(得分:2)

您的时间观察并不令人惊讶。由于回溯,Java正则表达式匹配可能非常慢(即,如果n是正则表达式的长度,则为O(2 ** n))。有时可以修改正则表达式以避免回溯,因此它会变快。

一个加速的想法是使用占有量词,在http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html中看到它们。另一个加速的想法是使用更少的|运算符。

试试这个:

private static final String COMMENT_MATCHER = "(//.*+)|(?s)(/[*].*?[*]/)";