2013-10-09 25 views
0

我的輸入是這樣的:拍攝集體吃一些字符

line 1 
**ER1.RIAA.SOMPSFIO(LIAOEE)   UTGD788 FDSJOFUZZÄ                                            line2  
JNDJZSDS ER1.RIAA.SIMEDFUA(AUDD)    YIRIHFIH1465EZZÄ  

line 3 
UJZRJOERERÃLDE,UIE='UJ1.DHZKZ5.OZDEZN98.AAERRE',I=DZEDE     POPZEOE** 

我想只得到字符段,即:

ER1.RIAA.SOMPSFIO 
ER1.RIAA.SIMEDFUA 
UJ1.DHZKZ5.OZDEZN98.AAERRE 

我的解決辦法是:

try { 
    StringBuilder sb = new StringBuilder(); 
    String line = br.readLine(); 

    while (line != null) { 
     nrligne++; 

int counter = 0; 

for (int i=0; i<line.length(); i++) { 
    if(line.charAt(i) == '.') { 
     counter++; 
    } 
} 

if (counter == 2) { 

    if (line.matches("^.*[A-Z0-9]+\\..[A-Z1-9]+.*$")){ 

     line= removeTroublesomeCharacters(line); 
     System.out.println("ligne vaut "+line); 

     Pattern dsnPattern = Pattern.compile("^.*([A-Z0-9]+)\\..([A-Z1-9]+)\\..([A-Z1-9]+).*$"); 
     Matcher m = dsnPattern.matcher(line); 

     if (m.matches()) { 
      String part1 = m.group(1); 
      String part2 = m.group(2); 
      String part3 = m.group(3); 

      System.out.println("part1 vaut "+part1); 
      System.out.println("part2 vaut "+part2); 
      System.out.println("part2 vaut "+part3); 
     }    
    } 

現在的結果是

ligne vaut ER1.RIAA.SOMPSFIO(LIAOEE)                        UTGD788 
part1 vaut 1 
part2 vaut IAA 
part2 vaut OMPSFIO 
ligne vaut PZFDSJOFUZZÃâ                                             ER1.RIAA.SIMEDFUA(AUDD)                        UOOO88 
part1 vaut 1 
part2 vaut IAA 
part2 vaut IMEDFUA 
ligne vaut UJZRJOERERÃLDE,UIE='UJ1.DHZKZ5.OZDEZN98',I=DZEDE                                                                  POPZEOE 
part1 vaut 1 
part2 vaut HZKZ5 
part2 vaut ZDEZN98 

文件輸入:http://uploadhero.co/dl/PWBLhi7d 我不明白爲什麼正則表達式吃每個字符的開始?有人可以幫我解決這個問題嗎?

回答

1

因爲您在dot之後使用了一個額外的字符,並且沒有將其包含在字符類中。

\\.. // this will match a dot, and then following single character. 

而且,使.*在你的正則表達式的開始.*?。由於量詞默認爲貪婪,因此它們將消耗所有字符,並且只在.之前留下一個單詞,以便與([a-z0-9]+)匹配。

您正則表達式更改爲:

"^.*?([A-Z0-9]+)\\.([A-Z1-9]+)\\.([A-Z1-9]+).*$" 

而且,由於使用的是PatternMatcher反正,我會考慮使用Matcher#find()方法,並建立模式,就像爲我所需要的零件:

Pattern dsnPattern = Pattern.compile("([A-Z0-9]+)\\.([A-Z1-9]+)\\.([A-Z1-9]+)"); 
Matcher m = dsnPattern.matcher(line); 

if (m.find()) { 
+0

你仍然必須在正則表達式本身兩個時期。你不打算只有一個? – Obicere

+0

@Obicere哎呀。修正了謝謝:) –

1

由於表達式的捕捉部分前後都有「吃東西」.*表達式,你希望捕獲的部分結果是被這些「填充物」所消耗。

您可以明確要求,前後[A-Z0-9]+羣的文字被非字母數字,像這樣:

"^.*(?<![A-Z0-9])([A-Z0-9]+)\\.([A-Z1-9]+)\\.([A-Z1-9]+)(?![A-Z1-9]).*$" 
  • (?<![A-Z0-9])表達的意思是「不[A-Z0-9]之前」
  • (?![A-Z1-9])表達方式「沒有跟着[A-Z1-9]

編輯:

先行是沒有必要的,因爲+是貪婪:

"^.*(?<![A-Z0-9])([A-Z0-9]+)\\.([A-Z1-9]+)\\.([A-Z1-9]+).*$" 

(貸記本去Rohit Jain

+0

'(?![A-Z1-9])'最後不需要,因爲由於它的貪婪,'+'量詞會自動消耗所有的單詞。 –

+0

此外,您可以在開始時將'。*'製作爲'。*?',以便在匹配[A-Z0-9]的第一個字符之前停止。 –

+0

@RohitJain由於回溯,''*?'可能會導致放緩,尤其是對於「誤報」較長的輸入。 – dasblinkenlight