2013-09-24 143 views
2

我遇到了一個與我的程序有關的小問題。它似乎凍結了,最有可能是由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。

+0

我相信你可以做一個兩杆的方法幫助調試 - 一個用於多行註釋,一個用於單行註釋。例如,有兩個常量'SINGLE_LINE_COMMENT_MATCHER'和'MULTI_LINE_COMMENT_MATCHER',每個都有自己的正則表達式。 – Meesh

+0

@Meesh匹配器匹配評論沒問題,只是當多行註釋沒有結束時。當你打字時,你遇到了。 – Obicere

+1

如果你用'Pattern.DOTALL'編譯它,你的模式可以被簡化爲更易讀(至少對我來說)版本'「// [[\ n] * | /[*].*?[*]/]'在開始時是否加入'(?s)'? – Pshemo

回答

2

您的時間觀察並不令人驚訝。由於回溯,Java正則表達式匹配可能非常緩慢(即O(2 ** n),如果n是正則表達式的長度)。有時可以修改正則表達式以避免回溯,所以它會變得很快。

一個加速的想法是使用佔有量詞,見http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html。另一個加速的想法是使用較少的|運營商。

試試這個:

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

哇,它的工作!我不是最好的正則表達式,我不知道這一點,謝謝。 – Obicere

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 "*/"