Even the Qtax example is very nice and straightforward, it does not fully correspond to me, because it returns {o{o}} instead of {f{o{o}}{bar}baz} .
After finding the time, my solution (using almost the same example):
Entrance:
string re = @"{(((?<Counter>{)*[^{}]*)*((?<-Counter>})*[^{}]*)*)*(?(Counter)(?!))}"; string str = "foo {bar} baz {foo{bar{{baz}a{a{b}}}}} {f{o{o}}{bar{a{b{c}}{d}}}baz} {foo{bar}baz}"; Console.WriteLine("Input: \"{0}\"", str); foreach (Match m in Regex.Matches(str, re)) { Console.WriteLine("Match: \"{0}\"", m); }
Output:
Input: "foo {bar} baz {foo{bar{{baz}a{a{b}}}}} {f{o{o}}{bar{a{b{c}}{d}}}baz} {foo{bar}baz}" Match: "{bar}" Match: "{foo{bar{{baz}a{a{b}}}}}" Match: "{f{o{o}}{bar{a{b{c}}{d}}}baz}" Match: "{foo{bar}baz}"
Some explanation, I increase the counter for each { and decrease the counter on each } . And finally, the regex matches only if the counter is empty ( (?(Counter)(?!)) ).
This seems to work for deep recursion, as well as with an alternative bracket.
See this site , which will also help me create this regular expression.
Hope this helps.
PS: If you want to match the string with the forgotten one} at the end, use:
string re = @"{(((?<Counter>{)*[^{}]*)*((?<-Counter>(}|$))*[^{}]*)*)*(?(Counter)(?!))(}|$)"; string str = "foo {bar} baz {foo{bar{{baz}a{a{b}}}}} {f{o{o}}{bar{a{b{c}}{d}}}baz} {foo{bar}b{az";
source share