2010-10-29 59 views
1

我知道,我知道,現在我有兩個問題,但這裏的正則表達式意味着我不必編寫兩個複雜的循環。相反,我有一個只有我明白的正則表達式,我纔會受僱於yonks。Java replaceAll()&split()違規

我有一個字符串,說stack.overflow.questions[0].answer[1].postDate,我需要得到[0]和[1],最好在數組中。 「簡單!」我的神經元驚歎,只需在輸入字符串中使用正則表達式和split方法;所以我想出了這個:

String[] tokens = input.split("[^\\[\\d\\]]"); 

這將產生以下:

[, , , , , , , , , , , , , , , , [0], , , , , , , [1]] 

哦,親愛的。所以,我想, 「你會做replaceAll在這種情況下?」:

String onlyArrayIndexes = input.replaceAll("[^\\[\\d\\]]", ""); 

它生產:

[0][1] 

嗯。爲什麼這樣?我正在尋找一個包含「[0]」作爲第一個元素和「[1]」作爲第二個元素的雙元素字符串數組。爲什麼Split在這裏不起作用,當Javadoc聲明他們都使用Pattern類時,按照Javadoc

總之,我有兩個問題:爲什麼用split()通話產生大陣與看似隨意的空格字符我是正確的思維中的replaceAll工作,因爲正則表達式替換所有字符不匹配「[」一個數字和「]」?我錯過了什麼,這意味着我期望他們產生類似的輸出(好吧,這是三個,請不要回答這個問題的線索?)。

回答

4
從我所看到的

很好的split沒有工作,它給你一個數組,用於存放每個匹配的字符串split,而不是一組中間帶數字的括號。

至於replaceAll我認爲你的假設是正確的。它將刪除所有內容(用""替換該匹配項),這不是您想要的。

API documentation

拆分此字符串周圍的 給定的正則表達式匹配。

此方法的工作原理就好像調用 雙參數拆分方法,其中 的給定表達式和極限參數 爲零。尾隨的空字符串是 因此不包含在 結果數組中。

字符串 「BOO:和:foo」 的,例如, 產生具有 以下結果這些表達式:由您提供的正則表達式定義的邊界

Regex  Result 
:  { "boo", "and", "foo" } 
o  { "b", "", ":and:f" } 
+0

謝謝,這是事實上,split爲我的正則表達式的每個匹配給了我一個元素;這是我不明白的! – 2010-10-29 08:29:39

2

這不是直接回答你的問題,但我想告訴你一個很好的API,將適合你的需要。

從谷歌Guava退房Splitter

因此,對於你的榜樣,你會使用這樣的:

Iterable<String> tokens = Splitter.onPattern("[^\\[\\d\\]]").omitEmptyStrings().trimResults().split(input); 

//Now you get back an Iterable which you can iterate over. Much better than an Array. 
for(String s : tokens) { 
    System.out.println(s); 
} 

此打印:
0
1

+0

一個很好的建議,謝謝。現在我只在這個特定的例子中使用正則表達式,但是如果我需要進一步的話,我會去番石榴。 – 2010-10-29 08:29:02

+0

Google Guava支持正則表達式。正如我在示例中所展示的那樣。 – 2010-10-29 08:30:48

2

split分割,所以這並不令人驚訝,你得到很多條目  —幾乎字符串中的所有字符都與你的正則表達式匹配,因此,根據定義,它們是出現分割的邊界。

replaceAll替換與您替換的正則表達式匹配,您的情況爲空白字符串。

如果你試圖抓住01,這是一個簡單的循環:

String text = "stack.overflow.questions[0].answer[1].postDate"; 
Pattern pat = Pattern.compile("\\[(\\d+)\\]"); 
Matcher m = pat.matcher(text); 
List<String> results = new ArrayList<String>(); 
while (m.find()) { 
    results.add(m.group(1)); // Or just .group() if you want the [] as well 
} 
String[] tokens = results.toArray(new String[0]); 

或者,如果它是總是正是其中的兩個:

String text = "stack.overflow.questions[0].answer[1].postDate"; 
Pattern pat = Pattern.compile(".*\\[(\\d+)\\].*\\[(\\d+)\\].*"); 
Matcher m = pat.matcher(text); 
m.find(); 
String[] tokens = new String[2]; 
tokens[0] = m.group(1); 
tokens[1] = m.group(2); 
1

的問題是那split這裏是錯誤的操作。

在Ruby中,我會告訴你string.scan(/\[\d+\]/),這將使你的陣列["[0]","[1]"]

Java沒有一個單一的方法相當,但我們可以用下面寫一個scan方法:

public List<String> scan(String string, String regex){ 
    List<String> list = new ArrayList<String>(); 
    Pattern pattern = Pattern.compile(regex); 
    Matcher matcher = pattern.matcher(string); 
    while(matcher.find()) { 
     list.add(matcher.group()); 
    } 
    return retval; 
} 

,我們可以把它作爲scan(string,"\\[\\d+\\]")

等效Scala代碼是:

"""\[\d+\]""".r findAllIn string 
+0

一個有趣的方法;謝謝! – 2011-07-04 08:00:53