\$\{((?:\{[^\{\}]*\}|[^\{\}]*)*)\}
If we meet an opening bracket, we look for its pair, and after the closing one we proceed as usual. This can't handle more than one level of nested brackets.
The main building block here in [^\{\}]*
- any non-bracket sequence. It can be surrounded by brackets \{[^\{\}]*\}
but it might be not (?:\{[^\{\}]*\}|[^\{\}]*)
. Any count of these sequences can be present, hence *
at the end.
Any level of nesting might require a recursive regex, not supported by Java. But any fixed amount can be matched by carefully extending this idea.