2010-10-04 15 views
0

在Java中,我試圖解析來自ASCII輸出文件的數據。下面顯示了一個數據樣本。這些值的格式爲精度5級別3,值之間不存在空格。使用Java的正則表達式類解析數字值

80.234 < - 1值
71.01663.129 < - 2值...
67.09159.25353.997
56.02759.77859.25057.749
55.86558.46958.64861.72855.969

什麼規律可以使用表達式模式來匹配數字值並將它們分組成組?模式(\ d +。\ d {1,3})匹配單個值。但是,對於指定行的組數,它不會給出預期的答案。例如,我期望以下找到10組。

String testPattern = "68.65761.25659.01057.67657.14857.06457.41658.77861.16268.641"; 

// create a pattern to match the output 
Pattern p = Pattern.compile("(\\d+\\.\\d{1,3}){10}"); 

Matcher m = p.matcher(testPattern); 

if (m.find()) 
{ 
    String group = m.group(); 
} 

回答

2

你希望它以某種方式打出來的個人號碼,因爲這是你如何匹配他們,但它不工作,那辦法。你的正則表達式所做的是一次捕獲一個數字並將其放入組#1。十次,它每次用新值覆蓋組#1的內容。完成後,group()會返回您發現的整個字符串,而group(1)將只返回第十個數字,即68.641

這是一個常見錯誤,可能是由於Java缺乏內置的「查找所有匹配」機制。 .NET有它的Matches()方法,PHP有preg_match_all(),Python有re.findall(),Perl和JavaScript有修飾符/g ......每種主要的味道都有一種機制來返回所有匹配數組或者遍歷匹配的迭代器,或者兩者都有。但是在Java中,您應該像在@KennyTM中演示的那樣,在while循環中調用find()

對於Java來說這是一個令人討厭的遺漏,但並不令人驚訝。它的效果是迫使我們編寫更詳細,更少慣用的代碼,從一開始就一直是Java的標誌。但是如果你真的想把這個任務減少到一線,那麼就有一箇舊的「分頭查看」技巧:

String[] result = source.split("(?=\\B\\d{2}\\.\\d{3})"); 

...或者:

String[] result = source.split("(?<=\\G\\d{2}\\.\\d{3})"); 
+1

+1令人敬畏的分裂()技巧! – helpermethod 2010-10-04 22:54:40

4

如果他們都格式相同,也許會更容易到剛剛在6個字符作爲一個字符串讀取,然後使用Double.parseDouble解析從字符串到雙?

2

你的正則表達式只有1個組。使用while循環來枚舉所有這些。 (見http://www.ideone.com/FNRsz):

String testPattern = "68.65761.25659.01057.67657.14857.06457.41658.77861.16268.641"; 
Pattern p = Pattern.compile("\\d+\\.\\d{1,3}"); 
Matcher m = p.matcher(testPattern); 

while(m.find()) // <--- 
    System.out.println(m.group()); 
+0

即使他的正則表達式是錯誤的,這將起作用。我猜測它應該是「\\ d \\ d \\。\\ d \\ d \\ d」。兩端的變長匹配組只能工作,因爲數字總是處於最大長度,所以貪婪是正確的。 – Darron 2010-10-04 20:33:45

1

使用Guava,固定長度Splitter將在這裏工作得很好。

Iterable<String> numbers = Splitter.fixedLength(6).split(testPattern); 

如果您要創建一個Function<String, Double>(叫,說,Numbers.doubleParser()),你甚至可以將數據輕鬆地轉換爲數字。 (當然你可以使用BigDecimal或什麼,而不是Double根據您的需要。)

private static final Splitter SPLITTER = Splitter.fixedLength(6); 

... 

public void someMethod(String stringToParse) { 
    for(Double value : Iterables.transform(SPLITTER.split(stringToParse), 
             Numbers.doubleParser())) { 
    ... 
    } 
}