Reputation: 339
This is giving me a hard time. I have an expression like this:
isnull(Num([abc]), [a], [b]) + sum([d])
I am trying to get everything that is enclosed within square brackets which is inside the isnull()
. So from the above example, I should get [abc], [a] and [b]
but not [d]
.
I have come up with this - isnull\((?:\[)(.*?)(?:\])
which gives me only [abc]
but not [a]
and [b]
.
What can I change in my regex pattern so that I get the correct matches? I am using VS2019 and C# if it matters.
Upvotes: 2
Views: 209
Reputation: 626802
You can use
(?i)\bisnull\((?>[^][()]|(?<x>\[[^][]*])|(?<o>)\(|(?<-o>)\))*(?(o)(?!))\)
See the regex demo. Details:
(?i)
- case insensitive matching enabled\b
- a word boundaryisnull\(
- isnull(
text(?>[^][()]|(?<x>\[[^][]*])|(?<o>)\(|(?<-o>)\))*
- either any char other than ]
, [
, (
and ]
, or a [...]
substring captured into Group "x", or a (
and an empty value is pushed onto Group "o" capture stack, or a )
and an empty value is popped from Group "o" capture stack, repeat zero or more times(?(o)(?!))
- if Group "o" capture stack is not empty, fail the current match\)
- )
char.See a C# demo:
var pattern = @"\bisnull\((?>[^][()]|(?<x>\[[^][]*])|(?<o>)\(|(?<-o>)\))*(?(o)(?!))\)";
var text = "isnull(Num([abc]), [a], [b]) + sum([d])";
var result = Regex.Matches(text, pattern, RegexOptions.IgnoreCase)
.Cast<Match>().Select(p => p.Groups["x"].Captures)
.ToList();
foreach (var coll in result)
foreach (var v in coll)
Console.WriteLine(v);
// => [abc], [a], [b]
Or, if you are after a single match:
var result = Regex.Match(text, pattern, RegexOptions.IgnoreCase)?.Groups["x"].Captures;
Console.WriteLine(string.Join(", ", result)); // => [abc], [a], [b]
See this C# demo.
Upvotes: 4