I am trying to create a .NET RegEx expression that will properly balance out my parenthesis. I have the following RegEx expression:
func([a-zA-Z_][a-zA-Z0-9_]*)\(.*\)
The string I am trying to match is this:
"test -> funcPow((3),2) * (9+1)"
What should happen is Regex should match everything from funcPow
until the second closing parenthesis. It should stop after the second closing parenthesis. Instead, it is matching all the way to the very last closing parenthesis. RegEx is returning this:
"funcPow((3),2) * (9+1)"
It should return this:
"funcPow((3),2)"
Any help on this would be appreciated.
By placing part of a regular expression inside round brackets or parentheses, you can group that part of the regular expression together. This allows you to apply a quantifier to the entire group or to restrict alternation to part of the regex. Only parentheses can be used for grouping.
The way we solve this problem—i.e., the way we match a literal open parenthesis '(' or close parenthesis ')' using a regular expression—is to put backslash-open parenthesis '\(' or backslash-close parenthesis '\)' in the RE. This is another example of an escape sequence.
Since parentheses are also used for capturing and non-capturing groups, we have to escape the opening parenthesis with a backslash. An explanation of how literalRegex works: / — Opens or begins regex. \( — Escapes a single opening parenthesis literal.
Brackets indicate a set of characters to match. Any individual character between the brackets will match, and you can also use a hyphen to define a set. You can use the ^ metacharacter to negate what is between the brackets.
Regular Expressions can definitely do balanced parentheses matching. It can be tricky, and requires a couple of the more advanced Regex features, but it's not too hard.
Example:
var r = new Regex(@" func([a-zA-Z_][a-zA-Z0-9_]*) # The func name \( # First '(' (?: [^()] # Match all non-braces | (?<open> \( ) # Match '(', and capture into 'open' | (?<-open> \) ) # Match ')', and delete the 'open' capture )+ (?(open)(?!)) # Fails if 'open' stack isn't empty! \) # Last ')' ", RegexOptions.IgnorePatternWhitespace);
Balanced matching groups have a couple of features, but for this example, we're only using the capture deleting feature. The line (?<-open> \) )
will match a )
and delete the previous "open" capture.
The trickiest line is (?(open)(?!))
, so let me explain it. (?(open)
is a conditional expression that only matches if there is an "open" capture. (?!)
is a negative expression that always fails. Therefore, (?(open)(?!))
says "if there is an open capture, then fail".
Microsoft's documentation was pretty helpful too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With