2012-06-05 83 views
1

我在正則表達式中不強壯,所以任何幫助將不勝感激。RegEx for [「abc」,[「123」,「cba」]]

我需要解析這些字符串:

["text", "text", ["text",["text"]],"text"] 

和輸出應該是(4弦):

text, text, ["text",["text"]], text 

我已經試過這種模式(\\[[^\\[,^\\]]*\\])|(\"([^\"]*)\")

String data="\"aa\", \"aaa\", [\"bb\", [\"1\",\"2\"]], [cc]"; 
Pattern p=Pattern.compile("(\\[[^\\[,^\\]]*\\])|(\"([^\"]*)\")"); 

但輸出是(引號本身在輸出中並不那麼關鍵):

"aa", "aaa", "bb", "1", "2", [cc] 

如何提高我的正則表達式?

+0

你試圖解析JSON?如果是這樣,有Java的庫可以做到這一點。 –

+0

@DelanAzabani不幸的是它不是JSON。 –

+0

不幸的是,這隱含地要求使用括號匹配(以確保您匹配正確的右括號),這通常不能用正則表達式來完成。但是,如果您知道括號最多可嵌套2或3層,則可以。是這樣嗎? – huon

回答

3

我不知道正則表達式是能夠做這樣的東西自己。這裏是一個辦法做到這一點,但:

// data string 
String input = "\"aa\", \"a, aa\", [\"bb\", [\"1\", \"2\"]], [cc], [\"dd\", [\"5\"]]"; 
System.out.println(input); 

// char that can't ever be within the data string 
char tempReplacement = '#'; 
// escape strings containing commas, e.g "hello, world", ["x, y", 42] 
while(input.matches(".*\"[^\"\\[\\]]+,[^\"\\[\\]]+\".*")) { 
    input = input.replaceAll("(\"[^\"\\[\\]]+),([^\"\\[\\]]+\")", "$1" + tempReplacement + "$2"); 
} 
// while there are "[*,*]" substrings 
while(input.matches(".*\\[[^\\]]+,[^\\]]+\\].*")) { 
    // replace the nested "," chars by the replacement char 
    input = input.replaceAll("(\\[[^\\]]+),([^\\]]+\\])", "$1" + tempReplacement + "$2"); 
} 

// split the string by the remaining "," (i.e. those non nested) 
String[] split = input.split(","); 

List<String> output = new LinkedList<String>(); 
for(String s : split) { 
    // replace all the replacement chars by a "," 
    s = s.replaceAll(tempReplacement + "", ","); 
    s = s.trim(); 
    output.add(s); 
} 

// syso 
System.out.println("SPLIT:"); 
for(String s : output) { 
    System.out.println("\t" + s); 
} 

輸出:

"aa", "a, aa", ["bb", ["1", "2"]], [cc], ["dd", ["5"]] 
SPLIT: 
    "aa" 
    "a, aa" 
    ["bb", ["1","2"]] 
    [cc] 
    ["dd", ["5"]] 

PS:代碼似乎複雜的「事業評論。這裏是一個更簡潔的版本:

public static List<String> split(String input, char tempReplacement) { 
    while(input.matches(".*\"[^\"\\[\\]]+,[^\"\\[\\]]+\".*")) { 
     input = input.replaceAll("(\"[^\"\\[\\]]+),([^\"\\[\\]]+\")", "$1" + tempReplacement + "$2"); 
    } 
    while(input.matches(".*\\[[^\\]]+,[^\\]]+\\].*")) { 
     input = input.replaceAll("(\\[[^\\]]+),([^\\]]+\\])", "$1" + tempReplacement + "$2"); 
    } 
    String[] split = input.split(","); 
    List<String> output = new LinkedList<String>(); 
    for(String s : split) { 
     output.add(s.replaceAll(tempReplacement + "", ",").trim()); 
    } 
    return output; 
} 

電話:

String input = "\"aa\", \"a, aa\", [\"bb\", [\"1\", \"2\"]], [cc], [\"dd\", [\"5\"]]"; 
List<String> output = split(input, '#'); 
+0

非常感謝 - 它是完美的作品!但是,它是一回事,我忘了說。如果有這樣的領域會怎麼樣:「文本,用逗號」?如何替換嵌套在引號中的逗號? –

+0

我剛剛編輯了代碼以避免這些逗號。 – sp00m

2

看來你在你的輸入中有遞歸,所以如果你有很多嵌套的[]正則表達式可能不是最好的解決方案。

爲此,我認爲使用簡單的算法使用indexOf()substring()會更好/更簡單。它也變得更加高效!

2

不幸的是,我不認爲你可以用Java正則表達式來做到這一點。你在這裏得到的是遞歸表達式。這種類型的語言對於基本的正則表達式是不可修正的(這正是java的實際所在)。

但是編寫該語言的小遞歸下降解析器並不難。

您可以檢查以下答案中尋找靈感:java method for parsing nested expressions

相關問題