You are looking for overlapping matches. Thus, just place your regex into a capturing group and put it inside a non-anchored positive lookahead:
Regex regex = new Regex(@"(?=(\(([^()]+| (?<Level>\()| (?<-Level>\)))+(?(Level)(?!))\)))", RegexOptions.IgnorePatternWhitespace);
The value you need will be inside match.Groups[1].Value
.
See the IDEONE demo:
using System;
using System.Text.RegularExpressions;
using System.IO;
using System.Linq;
public class Test
{
public static void Main()
{
var input = "abc(test)def(rst(another test)uv)xy";
var regex = new Regex(@"(?=(\(([^()]+| (?<Level>\()| (?<-Level>\)))+(?(Level)(?!))\)))", RegexOptions.IgnorePatternWhitespace);
var results = regex.Matches(input).Cast<Match>()
.Select(p => p.Groups[1].Value)
.ToList();
Console.WriteLine(String.Join(", ", results));
}
}
Results: (test)
, (rst(another test)uv)
, (another test)
.
Note that unanchored positive look-aheads can be used to find overlapping matches with capturing in place because they do not consume text (i.e. the regex engine index stays at its current position when trying to match with all the subpatterns inside the lookahead) and the regex engine automatically moves its index after match/failure making the matching process "global" (i.e. tests for a match at every position inside an input string).
Although lookahead subexpressions do not match, they still can capture into groups.
Thus, when the look-ahead comes to the (
, it may match a zero-width string and place they value you need into Group 1. Then, it goes on and finds another (
inside the first (...)
, and can capture a substring inside it again.