0

I need to match the characters between the innermost set of parentheses in a string, but allowing empty parens such as '()'. As best I can tell some kind of negative lookahead is needed here (and it is completely different than the question for which it is marked as duplicate)

An initial version, which does not properly include '()' is:

var re = new Regex(@"\(([^()]+)\)");

Some test examples:

x (a) y          -> a
x (a b) y        -> a b
x (a b c) y      -> a b c
x (a b() c) y    -> a b() c
x (a() b() c) y  -> a() b() c
x (a b() c()) y  -> a b() c()
x (a b(a) c) y   -> a
x (a (b() c)) y  -> b() c
x () y           -> empty

 

And a c# test method (adapt for your assertion library):

var re = new Regex(@"\(([^()]+)\)");

string[] tests = {
    "x (a) y", "a",
    "x (a b) y", "a b",
    "x (a b c) y", "a b c",
    "x (a b() c) y", "a b() c",
    "x (a() b() c) y", "a() b() c",
    "x (a b() c()) y", "a b() c()",
    "x (a b(a) c) y", "a",
    "x (a (b() c)) y", "b() c",
    "x () y", ""
};

for (int i = 0; i < tests.Length; i+=2)
{
    var match = re.Match(tests[i]);
    var result = match.Groups[1].Value;
    Assert.That(result, Is.EqualTo(tests[i + 1]));
}
rednoyz
  • 1,318
  • 10
  • 24
  • Research capture groups. Once you have that piece of the puzzle, you should be able to fit the rest. – Jason P Sallinger May 15 '18 at 20:33
  • 1
    @wiktor-stribiżew I think you may have missed something here. First, your regex is not a valid answer (see the test cases). Second, this is a very different question than the one for which you have marked it as duplicate. How can I edit the question to make this more clear? – rednoyz May 16 '18 at 03:45

1 Answers1

3

You could use something like this: (No need for Lookarounds)

\(((?:[^()]|\(\))+)\)

The adjustments made to your regex:

Added the [^()] in a non-capturing group along with an alternative |\(\) so it can match either a character other than ( and ) or empty parentheses ().

Try it online.

Alternatively, you could get rid of the capturing group if you don't need it and have your matches in full matches instead of groups by using Lookarounds like this:

(?<=\()(?:[^()]|\(\))+(?=\))

That way, you can access your matches directly using match.Value instead of match.Groups[1].Value.

Here's a demo.

Please let me know if there's anything not clear.

  • Nice -- please also see https://stackoverflow.com/questions/50560112/matching-balanced-parentheses-before-a-character – rednoyz May 28 '18 at 06:32