In C# programming, you often encounter such a requirement, which requires matching the contents in pairs of brackets, but the syntax of ?R in general regular expressions does not seem to be supported in C#. After some search and testing, the following description was finally found.
/( It should be \(not escaped by / but \ to escape
Match nested constructs
Microsoft has included an interesting innovation to match stable constructs (historically, this is something that regular expressions can't do). This is not easy to grasp—although this section is short, be careful, it is very obscure.
It might be easier to start with an example, so I started with this code:
Regex r = new Regex(@"/((?>[^()]+|/((?<DEPTH>)|/)(?<-DEPTH>))*(?(DEPTH)(?!))/)");
This matches the first fully paired bracket group, such as "(yes (here) OK)" in "before (nope (yes (here) OK) after". Note that the first left bracket is not matched because there is no close bracket that matches it.
Here is an overview of how it works:
1. When each "(" is matched, add a "(?<DEPTH>)" here to tell the regular expression system the depth of the current bracket nesting ("/(" at the beginning of the regular expression is not included here).
2. When each ")" is matched, "(?<-DEPTH>)" is reduced by one from the depth value.
3. "(?(DEPTH)(?!))" ensures that the depth is zero before matching the last closing bracket.
The reason it works is that the engine's reverse stack saves the trajectory of the successful group. "(?<DEPTH>)" is nothing more than a grouping construct with a name, which will always match successfully (not match anything). And since it is placed immediately after "/(", its successful match (still on the stack until removed) is used for the count of the opening bracket.
Translator's note: Another way of writing is "(?<DEPTH>/()",I personally prefer this form rather than "/((?<DEPTH>)". The same is true for the subsequent "/)(?<-DEPTH>)" as well.
In this way, the count of the successfully matched packet named "DEPTH" is established on the reverse stack. When we find the closing bracket, we also want to subtract one from the depth value, which is implemented by the .NET special syntax construction "(?<-DEPTH>)" which will remove the most recent matching "DEPTH" grouping from the stack. If there is no record on the stack, the "(?<-DEPTH>)" group match fails, preventing the regular expression system from matching the redundant closing brackets.
Finally, "(?(DEPTH)(?!))" is an assertion for "(?!)" if the "DEPTH" grouping has been successful so far. If it is successful when we match here, there is an unpaired left bracket that has not been removed by "(?<-DEPTH>)". In this case, we want to stop the match (we don't want to match an unpaired parentheses), so we use "(?!)", which is a "zero-width negative prediction lead assertion" that continues to match only if the subexpression does not match the right side of this position.
This is how to match nested structures in .NET's regular expression implementation.
The above content seems difficult to understand. In fact, if it is difficult to understand, it is simple, then don’t understand it. As long as you can use it, it will be OK. Replacing() with the characters you want will help you solve many of your problems.
The following is a test case based on this usage
private void button3_Click( object sender, EventArgs e ) { Regex r = new Regex( @"/[(?>[^/[/]]+|/[(?<DEPTH>)|/](?<-DEPTH>))*(?(DEPTH)(?!))/]" ); StringBuilder sb = new StringBuilder(); MatchString( "[111[222[333]]][222[333]][333]", r, sb ); ( (), "Information obtained" ); } private void MatchString( string OutString, Regex r, StringBuilder sb ) { MatchCollection ms = ( OutString );// Get all matches foreach ( Match m in ms ) { if ( ) { ( [0].Value ); MatchString( [0].( 1, [0]. - 1 ), r, sb );// Remove the "[" and "]" of the matching head and tail to avoid falling into a dead loop recursion and causing overflow } } return; }
Can get
[111[222[333]]] [222[333]] [333] [222[333]] [333] [333]
I believe that the description in this article has certain reference value for everyone's C# programming.