2009-11-11 27 views
3

我有類似以下的字符串:從字符串中提取兩個數字

「一些值是25,但不能更大然後12」

我想提取的兩個數字來自字符串。

這些數字是整數。

第一個數字前面可能沒有文字,第二個數字後面可能沒有文字。

我試圖用一個正則表達式和團體去做,但悲慘地失敗了:

public MessageParser(String message) { 
    Pattern stringWith2Numbers = Pattern.compile(".*(\\d?).*(\\d?).*"); 
    Matcher matcher = stringWith2Numbers.matcher(message); 
    if (!matcher.matches()) { 
     couldParse = false; 
     firstNumber = 0; 
     secondNumber = 0; 
    } else { 
     final String firstNumberString = matcher.group(1); 
     firstNumber = Integer.valueOf(firstNumberString); 
     final String secondNumberString = matcher.group(2); 
     secondNumber = Integer.valueOf(secondNumberString); 

     couldParse = true; 
    } 
} 

任何幫助apreciated。

回答

3

你的".*"模式正在貪婪,他們習慣於貪婪,儘可能多地吞噬 - 這將是整個字符串。因此,第一個".*"與整個字符串匹配,使其餘部分無效。此外,您的"\\d?"子句指示一個數字,這恰好是可選的,這兩者都不是您想要的。

這可能更多的是符合你拍攝的內容:

Pattern stringWith2Numbers = Pattern.compile(".*?(\\d+).*?(\\d+).*?");

當然,因爲你並不真正關心的東西之前或後的數字,爲什麼與他們打擾?

Pattern stringWith2Numbers = Pattern.compile("(\\d+).*?(\\d+)");

這應該做的伎倆。

編輯:艾倫摩爾在評論中指出了我的解決方案中存在的一些問題,從寫作對峙真棒漫畫中抽出時間。對於初學者來說,如果字符串中只有一個多位數字,我的解決方案就錯了。將它應用到「這個123是一個不好的字符串」時,會導致它在簡單失敗時返回「12」和「3」。一個更好的正則表達式將規定必須有至少一個非數字字符分隔的兩個數字,像這樣:

Pattern stringWith2Numbers = Pattern.compile("(\\d+)\\D+(\\d+)");

此外,matches()應用模式的整個串,基本上包圍它^$; find()會做到這一點,但這不是OP所使用的。因此,與matches()堅持,我們需要帶回那些「無用」的條款在前面,這兩個數字之後。 (雖然讓他們明確地匹配非數字字符而不是通配符是更好的形式。)因此,它看起來像:

Pattern stringWith2Numbers = Pattern.compile("\\D*(\\d+)\\D+(\\d+)\\D*");

...這,必須指出,是該死的幾乎相同,以jjnguy的答案。

+0

數字模式之間的「。*」會不會「吃掉」第二個數字? – MartinStettner

+1

不是。星號後面的問號表示它應該匹配儘可能最短的字符串 - 因此,它會匹配第二個數字之前的所有內容。 – BlairHippo

+0

......雖然,因爲兩位數的條款是不可選了,問號是那麼重要 - 如果你是絕對肯定會有兩個字符串中只有兩個數字,你不需要它。但是,如果有更多的數字,這很重要。使用「1和2和3」作爲示例字符串:使用問號,可以獲得1和2。沒有,1和3將是兩個提取的值。 – BlairHippo

8

你的模式應該更像:

Pattern stringWith2Numbers = Pattern.compile("\\D*(\\d+)\\D+(\\d+)\\D*"); 

你需要接受\\d+因爲它可以是一個或多個數字。

+0

正如指出的下方,有 「*」, 「吃掉」 整個字符串... – MartinStettner

+0

豈不\ d *(\ d +)^ \ d] *(\ d +)^ \ d *稍多適當?因爲我們明確不想要數字和。有可能在我們到達\ d之前匹配一個數字。 –

+0

我討厭正則表達式,謝謝。 – jjnguy

2

您的正則表達式匹配,但所有東西都會被第一個.*吃掉,其餘的匹配空字符串。

將您的正則表達式更改爲"\\D*(\\d+)\\D+(\\d+)\\D*"

這應該被理解爲:至少一個數字後跟至少一個不是數字的字符,後面至少有一個數字。

+2

開頭和結尾的'。如果你使用'匹配()'方法爲OP做*'是必要的。你的正則表達式可以和'find()'方法一起工作,它執行更傳統的「它存在於某處」的正則表達式匹配。 –

+0

感謝Alan的澄清,我編輯了我的答案。 –