JRegex does not seem to support recursive matching, so I suggest you just use java.util.regex
and set a limit upon the number of levels of nesting.
For example, to allow up to fifty levels of nesting, with an 'unlimited' number of bracket pairs on each level (except the deepest), you could use
// 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}
*/
The above builds a regular expression by taking one that could be used if recursive matching was supported (?>\\{(?:[^{}]*+|(?R))+\\})
and repeatedly substituting the (?R)
for the whole pattern.
Because there are many nested quantifiers in the expression that is created, atomic grouping (?>)
and the possessive quantifier +
are used to limit backtracking and ensure that the regex fails fast if it cannot find a match. Although the regex may be long, it will be efficient.
If you don't want or are unable to set a limit on the nesting, or if the idea of a lengthy regex is worrying, you could parse the nested brackets by simply iterating over the file text and tracking the number of opening and closing brackets, for example
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); }
That seems like a lot less trouble than interacting with Perl, but see answers such as How should I call a Perl Script in Java? if that is what you want to do.