2011-06-14 54 views
1

在下面,我期望第二個find()成功,但它不。爲什麼? 與量詞不匹配後,Java的matcher.find()保留了什麼樣的狀態?

Matcher matcher = 
    Pattern.compile("\\s*asdf").matcher("apple banana cookie"); 

// returns false as expected 
matcher.find(); 

// resets groups (that weren't being explicitly being used anyway), but not state. 
matcher.usePattern(Pattern.compile("\\s*banana")); 

// returns false, expected true. 
System.out.println(matcher.find()); 

如果量詞從第一正則表達式去除(簡單地成爲「ASDF」),所述第二匹配成功。查看Matcher對象會揭示某些組信息在第一次不成功的find()之後存儲,儘管我不會期望它。 Find()是supposed可以在開始處(如果沒有先前的匹配)或者在最後一次成功匹配的索引處開始。 UsePattern()爲supposed以保留匹配器在輸入中的位置,並放棄組信息(即,我沒有明確使用)。

我錯過了一些東西,但我不知道是什麼。我懷疑我必須實現這與lookAt()和更新區域(如this example),但我不知道爲什麼這種方法不起作用。

回答

1

看起來像文檔有點誤導(或實際上,它只是沒有指定)失敗後調用find()時的行爲。

我想預計使用情況是find()被重複調用直到失敗,但從未失敗後沒有重新設置。

望着source code確認Matcher有索引(場last),從它開始做下一行時「找到()」進行搜索,當find()出現故障,該指數是先進到最後,不重啓。

reset()重置該索引,usePattern()沒有。

+0

在我的實現中,我使用匹配器在遞歸調用中維護狀態,因此要解決我原來的問題,我保存舊區域並調用區域(oldStart,oldEnd),在設置邊界之前重置匹配器。 – 2011-06-14 18:19:16

+0

該區域與內部「最後」字段不同。您可以測試它:調用find不會更改該區域。 – trutheality 2011-06-14 18:34:57

5

你的第一個正則表達式消耗整個字符串(\\\\s*)。當第二個正則表達式運行時,沒有什麼可匹配的。

如果你打電話matcher.reset()它按預期工作。

+0

好的,仔細閱讀[Matcher JavaDoc](http://download.oracle.com/javase/1.5.0/docs/api/java/util/regex/Matcher.html)並記住這一點「匹配器在其輸入的一個子集中找到稱爲區域的匹配項。默認情況下,該區域包含所有匹配器的輸入。」據我所知,在文檔中只定義了region()方法來修改區域(儘管看起來相當清楚該區域在其他時候被修改,因此混淆)。那麼,find()實際上會修改該區域? – 2011-06-14 01:36:57