2012-06-05 2 views
1

Я не силен в regex, поэтому любая помощь будет оценена.RegEx для ["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

Большое спасибо - это прекрасно! Но это одно, что я забыл сказать. Что делать, если будет такое поле: «text, with, comma»? Как заменить запятую, вложенную в кавычки? –

+0

Я только что отредактировал код, чтобы избежать этих запятых. – sp00m

2

Кажется, что у вас есть рекурсия на вашем входе, поэтому, если у вас много вложенных [] регулярных выражений, вероятно, не лучшее решение.

Для этой цели я считаю, что лучше использовать простой алгоритм, используя indexOf() и substring(). Это также более эффективно!

2

К сожалению, я не думаю, что вы можете сделать это с помощью регулярных выражений Java. То, что у вас здесь, - это рекурсивное выражение. Этот тип языка не может быть изменен для основных регулярных выражений (что и есть на самом деле java Pattern).

Но это не так сложно написать небольшой рекурсивный парсер спуска для этого языка.

Вы можете проверить следующий ответ для вдохновения: java method for parsing nested expressions

Смежные вопросы