2010-11-22 82 views
5

我正嘗試使用Java正則表達式來匹配跨越多行的模式。該模式具有與「A」後緊跟50個字符,然後與後緊跟50個字符「B」開頭的一行或多行開始一條線:Java正則表達式來查找特定長度的多行

A... // exactly 50 chars after the A 
B... 
B... 

Java正則表達式似乎不支持這然而。

下面是用於一個A和一個B線工作的正則表達式:

A.{50}[\\n[\\n\\r]]B.{50}[\\n[\\n\\r]] 

這裏是修飾以找到一種或多種B線相同的正則表達式:

A.{50}[\\n[\\n\\r]][B.{50}[\\n[\\n\\r]]]+ 

此正則表達式僅發現然而,第一條B線上的前B字。我使用[\\n[\\r\\n]]來處理DOS和UNIX換行符。打開MULTILINE模式不會影響結果。

問題似乎是,當我使用括號'+'將B行的正則表達式轉換爲可捕獲多行的字符類時。

有沒有關於Java正則表達式的東西,不允許'。'字符或大括號來指定確切的行長度?

+0

「A」後面有一個A行,後面有50個字符,然後是多個B行,後面跟着「B」後面的50個字符。 stackoverflow並沒有保留上面顯示的A和B行之間的換行符。 – 2010-11-22 17:57:30

回答

0

在下面的正則表達式:

(A[^\r\n]{50}(\r\n|\n))(B[^\r\n]{50}(\r\n|\n))+ 

我以前[^\r\n]匹配,是不是\r\n任何字符。例如,如果您有數字,則可以用[\d]替換它。

http://www.myregextester.com/?r=b7c3ca56

在這個例子中,正則表達式所有除最後一行相匹配。

+0

這似乎工作。 – 2010-11-22 18:49:23

0

同時處理的Unix和DOS風格的換行符,你可以使用:

\\r?\\n 

而且您的分組的一個或多個B線的方式不正確,你正在使用[]爲分組,您應該使用(?: )代替。

試試這個正則表達式:

A.{50}\\r?\\n(?:B.{50}(?:\\r?\\n)?)+ 

Regex tested here

+0

只是爲了它,因爲你發佈了一個紅寶石版本。這是一個偉大的正則表達式測試器的Python版本http://www.pythonregex.com/ – Falmarri 2010-11-22 18:38:28

+0

謝謝。這似乎工作。 – 2010-11-22 18:46:54

0

這應該工作:

String input = "A1234567890\nA12345678\nA12345678\nB12345678\nA123456\nA1234567\nZA12345678\nB12345678\nA12345678\nB12345678\nB12345678\nB12345678\nB1234567\nA12345678\nB12345678"; 

String regex = "^A.{8}$((\\r|\\r\\n|\\n)^B.{8}$)+(\\r|\\r\\n|\\n|\\z)"; 

Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE); 
Matcher matcher = pattern.matcher(input); 

while (matcher.find()) { 
System.out.println("matches from " + matcher.start() + " to " + matcher.end()); 
} 

注:

  1. 使用^$MULTILINE避免匹配開始 「ZA」 的路線。
  2. 使用(\\r|\\r\\n|\\n)來匹配unix,windows和舊mac-os行。
  3. 使用(\\r|\\r\\n|\\n|\\z)最後B線與最終的行沒有

Opsss匹配,我用8代替50以增加可讀性。

0

點和大括號工作正常;這是你的正則表達式的其餘部分是錯誤的。檢查了這一點:

Pattern p = Pattern.compile("^A.{50}(?:(?:\r\n|[\r\n])B.{50})+$"); 

(?:\r\n|[\r\n])一個CRLF序列中,只有CR,或僅LF匹配。 (我可以像你一樣使用兩個反斜槓,但也可以)。

如果您使用正則表達式從某些較大的文本中提取匹配項,則需要在MULTILINE模式下進行編譯,以便^$錨點可以在行邊界處匹配。如果它應該匹配整個字符串,則將其保留爲默認模式,以便它們只匹配字符串的開頭和結尾。

0

正確的方式來匹配斷行的順序是:

"(?:(?>\\u000D\\u000A)|[\\u000A\\u000B\\u000C\\u000D\\u0085\\u2028\\u2029)" 

這是Java的slackbashy串符號,當然,就像你可能會傳遞給Pattern.compile。更合理的語言讓你與這個簡單的獲取:

(?:(?>\x0D\x0A)|\v) 

但隨後,Java的正則表達式從來沒有類似的東西合理的,甚至這實際上是how bad they really are輕描淡寫。 Java的poor support for whitespace detection只是它的正則表達式中無數的麻煩點之一。

祝你好運:你需要它。 ☹

0

這應該工作太:

Pattern regex = Pattern.compile("^A.{50}$\\s+(?:^B.{50}$\\s*)+(?:^|\\z)", Pattern.MULTILINE); 

這背後的原因是,在該行,$匹配在該行的末尾開始^比賽,(可選)換行符之前,和\s匹配包括\r\n的空格。由於我們在$^之間使用它,因此它只能匹配換行符,而不能匹配其他空格。

(?:^|\\z)用於確保在B行的最後一次重複之後,我們不會意外地匹配行中的任何前導空格。如果行從不以空格開始,那麼可以放棄這一點。