Search code examples
.netregexbalancing-groups

Balancing Groups in .Net Regex not nesting correctly


I am trying to wrap my head around a bug I am finding with the .Net balancing groups regex.

I am trying to match !{} as an opening/closing combination.

Current Regex -> !{[^!{}]*(((?<Open>!{)[^!{}]*)+((?<Close-Open>})[^!{}]*)+)*(?(Open)(?!))}

this matches !{some random stuff here} successfully. It also matches !{some other Stuff !{} with nesting}

However, it DOES NOT match this !{some stuff with {} just curly braces} at all. It seems the '{}' inside the string is causing some issues as it seems to think that the group is no longer "balanced"

I am testing all of this on http://regexstorm.net/tester which is a great place for .Net specific regex testing.

To be fair I am no regex expert, and have unashamedly copied / manipulated the regex from this site http://www.regular-expressions.info/balancing.html

I don't need it to be able to match nesting as I will use c# to traverse recursively into the matches, but i just need to be able to get a positive match on the example that is failing above.

UPDATE

Here is what the initial goal of the pattern is. Much like with Razor pages where it matches @{ some C# code here } as code blocks, I have used a pattern of !{some code here} to demarcate sections of code inside a html page. I have written a website for a client where they use those "replacers" to execute custom logic inside their html pages. so for example :

<p> Hello !{CurrentSession.GetUser().FirstName}</p>

When the page is rendered out I use Regex to identify those "replacers" and then use Springframework.Net to execute that code against a known context.

This has all worked brilliantly since 2009 ( yes over 10 years ago ! ) but now they are starting to use a lot more Json type data and that is where I discovered this bug / issue with my regex.

So Imagine this example

<script type="text/javascript">

 var myArray = [ !{CurrentSession.GetUser().GetDataOrDefault( '{Name:"MyName"}' )} ];

</script>

As you can see with the above example, there is Json with curly braces '{}' inside the replacer I'm trying to match !{} and that is where the regex is failing.

PS the '!' is NOT optional it MUST open with '!{' and close with '}'

thanks in advance


Solution

  • You may use

    !{(?>[^{}]+|(?<Open>{)|(?<Close-Open>}))*}
    

    The regex will find an exclamation mark, and then a { followed with any amount of paired nested curly braces up to the matching close brace.

    See the regex demo.

    Details

    • !{ - a !{ substring
    • (?>[^{}]+|(?<Open>{)|(?<Close-Open>}))* - zero or more repetitions (allowing no backtracking into the alternation atomic group) of
      • [^{}]+| - 1+ chars other than { and }, or
      • (?<Open>{)| - a { char pushed on to Group "Open" stack
      • (?<Close-Open>}) - a } char popped from Group "Open" stack saving the substring matched in Group "Close"
    • } - a } char.