Regex noob here
I have the following string:
This is a message {key1} {{key2}} {{{key3}}}, and includes {key4}.
I'm trying to extract anything between the outer curly braces. Expected matches:
key1
{key2}
{{key3}}
key4
Most SO examples cover matches on a single curly brace or a double curly brace, but not both or any variation of. Expressions like [^{\}]+(?=})
will get me the content between the inner braces, and (?<=\{).*?(?=\})
will get the leading braces except the first, but not the trailing ones.
You may get the results you need using
var results = Regex.Matches(text, @"{({*[^{}]*}*)}")
.Cast<Match>()
.Select(x => x.Groups[1].Value);
See the regex demo.
Regex details
{
- an open curly brace({*[^{}]*}*)
- Group 1:
{*
- 0 or more open curly braces[^{}]*
- 0 or more chars other than curly braces}*
- 0 or more close curly braces}
- a close curly braceBonus solution (provided in comments)
If you need to extract a string between nested curly braces you can use
\{((?>[^{}]+|(?<c>{)|(?<-c>}))*)(?(c)(?!))}
See this regex demo. Here,
\{
- matches a {
char((?>[^{}]+|(?<c>{)|(?<-c>}))*)
- Group 1: zero or more repetitions of either one or more chars other than {
and }
, or a {
char (pushed onto Group "c" stack) or a }
char (popped off the Group "c" stack)(?(c)(?!))
- a check: if Group "c" still has a value on its stack, trigger backtracking (caused by "fail" with unconditional (?!)
lookahead)}
- a }
char.And if they can be overlapping:
(?=(\{((?>[^{}]+|(?<c>{)|(?<-c>}))*)(?(c)(?!))}))
Just get match.Groups[1].Value
to get the whole match, or match.Groups[2].Value
to get text inside braces only after you get a match.