Search code examples
c#regex.net-core

Regex: Get anything between any curly braces


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.


Solution

  • 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 brace

    Bonus 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.