2012-05-31 38 views
1

我有正則表達式,它解析模板中使用的freemarker宏的所有名稱(例如從<@macroName />我只需要macroName)。模板通常非常大(3萬個字符)。 用正則表達式的Java代碼如下所示:Java的正則表達式matcher.find偶爾會失敗

Pattern pattern = Pattern.compile(".*?<@(.*?)[ /].*?", 
            Pattern.DOTALL | Pattern.UNIX_LINES); 
Matcher matcher = pattern.matcher(inputText); 
while(matcher.find()){ 
    //... some code 
} 

但有時會發生,我得到這個異常:

java.util.regex.Pattern$Curly.match1(Pattern.java:3814) 
java.util.regex.Pattern$Curly.match(Pattern.java:3763) 
java.util.regex.Pattern$Start.match(Pattern.java:3072) 
java.util.regex.Matcher.search(Matcher.java:1116) 
java.util.regex.Matcher.find(Matcher.java:552) 
... 

是否有人知道爲什麼會發生或可能有人讓我知道,如果正則表達式我使用已經優化好了嗎? 謝謝

+1

什麼是異常(和消息)?你只發布堆棧跟蹤 –

+0

我甚至感到驚訝,你的正則表達式匹配任何你需要的東西。其中有很多問題,從重複使用'。*?'到'[/]'開始,這不符合你的想法。我建議你看看Jeffrey Friedl和http://regex.info。 – dda

回答

1

您可以擺脫領先的.*?,因爲您不需要在比賽之前/之間消耗文本。正則表達式引擎將負責掃描下一場比賽,並且它會比你所做的更有效率。只要給它的標籤本身的模式,並擺脫它的方式。

你可以擺脫尾隨.*?因爲它從來沒有做任何事情。想一想:它試圖匹配零個或更多的任何字符,勉強。這意味着它試圖做的第一件事是什麼都不匹配。該嘗試會成功(總是可以不匹配),所以它永遠不會嘗試消耗更多的字符。

你可能想是這樣的():

<@(\w+)[\s/] 

...或Java的發言:

Pattern p= Pattern.compile("<@(\\w+)[ /]"); 

你不需要DOTALL(沒有點)或任何其他修飾符。

+0

非常感謝你..這正是我需要的 – Daniel

3

對於<@macro macroName />你的正則表達式看起來有點複雜。或者有一些東西(特殊情況)<@macro macroName />沒有描述,或者正則表達式太努力了。嘗試:

<@macro\s+(\S+)\s+/> 

您應該在組#1中具有該宏的名稱。

+0

好的,謝謝你的建議..我實際上改變了我想從<@macro macroName />解析到<@macroName />的帖子中的字符串:) – Daniel

+0

dda的答案仍然可以適用於較小的更改 - 使用<@(\S+)\s+/> – rlinden

+0

@ rlinden謝謝你的修改:-) – dda