2013-01-15 71 views
0
{{ info {{ abc}} {{ last}} }} {{ fast}} 

在這個字符串中,我需要提取數據,使起始和結束括號平衡。即,在這種情況下,我會使用需要Java正則表達式:選擇均衡括號數據

  1. {{ info {{ abc}} {{ last}} }}
  2. {{ fast}}

正則表達式IM目前

(\\ {\\{.*\\}\\}) * 

,但它給我的整個字符串而不是一個我期待。如何正確地做到這一點?

String line="{{ Infobox {{aks}} {{ska}} }} akshat {{ las}}"; 
String pattern; 
System.out.println(line); 
Pattern r=Pattern.compile("(\\{\\{.*\\}\\})*"); 
Matcher m=r.matcher(line); 

輸出是整串......不是我預期

回答

3

這是不可能解決這個使用Java正則表達式。

正則表達式(在數學意義上)無法解析遞歸語法的輸入。你需要一個遞歸語法來描述一種語言(比如這個),其中任意嵌套的括號是平衡的。

儘管Java正則表達式比數學正則表達式更強大,但它們仍不支持遞歸。 (在某些語言的正則表達式引擎做...但你問在Java的解決方案。)


您可以創建一個處理一個有限數量的嵌套括號水平的正則表達式,但它會是醜陋和低效率......尤其是如果你不得不面對不平衡的括號輸入錯誤! (並且效率問題也適用於涉及遞歸正則表達式的假設解決方案......)

但是,我建議對字符串進行標記並做一個簡單的臨時解析,計算括號級別並在級別返回時發出結果歸零。這是一個簡單的編碼問題:請參閱@Evgeniy Dorofeev的答案作爲出發點。 (但請注意,他沒有處理2個錯誤案例...)

+0

(至少不是Java正則表達式。PHP/Perl的/ .NET正則表達式引擎*可以*做遞歸匹配)。無論如何,目前使用的實際正則表達式引擎都不限於常規語法,因此規律性不再是一個標準。 –

+0

但是,這對於Java正則表達式是正確的。 –

+0

那麼還有其他方法可以做到嗎? –

0

我不認爲你可以用正則表達式來完成。但是,如果你有興趣的其他解決方案我可以建議

String s = "{{ info {{ abc}} {{ last}} }} {{ fast}}"; 
    List<String> l = new ArrayList<>(); 
    StringBuilder sb = new StringBuilder(); 
    int balance = 0; 
    for(char c : s.toCharArray()) { 
     sb.append(c); 
     if (c == '{') { 
      balance++; 
     } else if (c == '}' && --balance == 0) { 
      l.add(sb.toString()); 
      sb.setLength(0); 
     } 
    } 
    System.out.println(l); 

輸出

[{{ info {{ abc}} {{ last}} }}, {{ fast}}]