Ответ 1
JRegex, похоже, не поддерживает рекурсивное сопоставление, поэтому я предлагаю вам просто использовать java.util.regex
и установить ограничение на количество уровней вложенности.
Например, чтобы разрешить до пятидесяти уровней вложенности с "неограниченным" числом пар скобок на каждом уровне (кроме самого глубокого), вы можете использовать
// Set the maximum number of nested levels required.
int max = 50;
String regex = "(?R)";
while (--max > 0) {
regex = regex.replace("(?R)", "(?>\\{(?:[^{}]*+|(?R))+\\})");
}
// Ensure no (?R) in the final and deepest replacement.
regex = regex.replace("(?R)", "\\{[^{}]*+\\}") + "|\\w+";
String str = " {{}{}} {abc} {{de}{fg}} hij {1{2{3{4{5{6{7{8{9{10{11{12{13{14{15{16{17{18{19{20{21{22{23{24{25{26{27{28{29{30{31{32{33{34{35{36{37{38{39{40{41{42{43{44{45{46{47{48{49{50}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} {end}";
Matcher m = Pattern.compile(regex).matcher(str);
while (m.find()) {
System.out.println(m.group());
}
/*
{{}{}}
{abc}
{{de}{fg}}
hij
{1{2{3{4{5{6{7{8{9{10{11{12{13{14{15{16{17{18{19{20{21{22{23{24{25{26{27{28{29{30{31{32{33{34{35{36{37{38{39{40{41{42{43{44{45{46{47{48{49{50}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
{end}
*/
Вышеописанное строит регулярное выражение, беря значение, которое можно было бы использовать, если было рекурсивное сопоставление поддерживалось (?>\\{(?:[^{}]*+|(?R))+\\})
и многократно подставляя (?R)
для всего шаблона.
Поскольку в выраженном выражении есть много вложенных кванторов, атомарная группировка (?>)
и квантификатор притяжения +
используются для ограничения обратного отслеживания и обеспечения быстрого выполнения регулярного выражения, если он не может найти совпадение. Хотя регулярное выражение может быть длинным, оно будет эффективным.
Если вы не хотите или не можете установить ограничение на вложенность, или если идея длинного регулярного выражения вызывает беспокойство, вы можете разобрать вложенные скобки, просто перебирая текст файла и отслеживая количество открытий и закрывающие скобки, например
List<String> list = new ArrayList<String>();
int strLen = str.length();
for (int i = 0; i < strLen; i++) {
char c = str.charAt(i);
if (c == '{') {
int b = 1;
StringBuilder sb = new StringBuilder("{");
while (b > 0 && i < strLen - 1) {
sb.append( c = str.charAt(++i) );
if (c == '}') b--;
else if (c == '{') b++;
}
list.add(sb.toString());
}
}
for (String s : list) { System.out.println(s); }
Это похоже на гораздо меньшую проблему, чем взаимодействие с Perl, но см. ответы, такие как Как я могу назвать Perl Script в Java?, если это то, что вы хотите сделать.