简体   繁体   中英

Regex: match everything inside closest opening and closing curly braces around expression

It's a bit hard to explain what I really want (better title suggestions are appreciated so people can find this easily in the future).

Suppose I have this:

{
    {
        $myTagThing$
    }
}

I want to match

{
    $myTagThing$
} 

ie match everything from the last { before $myTagThing$ until the first } after $myTagThing$ .

So I thought I'd need this \\{.*\\$myTagThing\\$.*\\} , but it will also match the first { and last } in the string (ie the whole example). Then I tried using a lookahead and a lookbehind (both negative) \\{(.*(?!\\{))\\$myTagThing\\$.*(?<!\\})\\} ( https://regex101.com/r/RfdHUH/1/ ). But this still doesn't work.

My theory is that I might be using lookahead and lookbehind the wrong way since this is the first time I use them.

Any ideas?

EDIT: flags are \\gms .

NOTE This was upvoted 3 times and marked as the accepted answer for revision 2 of this question, before the question was changed to a different scenario, and this answer was unaccepted.

You need to look for: opening-curly-brace, then a sequence of characters which are not open or close-curly-brace, then close-curly-brace.

Specifically: {[^{}]*}

EDIT: This addresses a { $myTagThing$ {} } scenario no longer included in question.

Regarding your updated question. What you want, in .NET, is called balanced groups . In other regex engines, balanced constructs/expressions . The terminology slightly varies, the syntax is wildly different between engines, and so is the behavior.

Anyway, to capture the largest {} contents possible, you want:

[^{}]*
(
((?'Open'{)[^{}]*)+
((?'Close-Open'})[^{}]*)+
)*
(?(Open)(?!))

(Set the ignore whitespace flag or collapse this regex). This is the core of your answer. We just modify it with the first and last line here:

\{[^{}]*myTagThing
[^{}]*
(
((?'Open'{)[^{}]*)+
((?'Close-Open'})[^{}]*)+
)*
(?(Open)(?!))
[^{}]*\}

regex storm

The "one regex" solution can get complicated fast, but if you find yourself using .NET regexes often, you might find the following worth looking into:

Searching for specific text inside balanced chars (recursive

The link above is where I had an issue where I was looking for a string like:

Type VAR.*while{{VAR++}} where the while could be followed by balanced {} . The bounty-awarded answer is the one you want to look at. It's a more complicated problem than yours, but you can see that it gets insane pretty quick:

Also see the official documentation on this feature:

https://docs.microsoft.com/en-us/dotnet/standard/base-types/grouping-constructs-in-regular-expressions#balancing_group_definition

Another way, modifying the OP's original approach:

\{{1}\s*\$myTagThing\$.*?\}

The {1} indicates matching the previous character exactly once. The \\s* captures white space. The .*? makes the search for the right brace non-greedy.

Of course if the thing is multiline you need to enable that as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM