Reputation: 10459
I know nothing about regex so I am asking this great community to help me out. With the help of SO I manage to write this regex:
string input = "((isoCode=s)||(isoCode=a))&&(title=s)&&((ti=2)&&(t=2))||(t=2&&e>5)";
string pattern = @"\((?>\((?<DEPTH>)|\)(?<-DEPTH>)|.?)*(?(DEPTH)(?!))\)|&&|\|\|";
MatchCollection matches = Regex.Matches(input, pattern);
foreach (Match match in matches)
{
Console.WriteLine(match.Groups[0].Value);
}
And the result is:
((isoCode=s)||(isoCode=a))
&&
(title=s)
&&
((ti=2)&&(t=2))
||
(t=2&&e>5)
but I need result like this (without first/last "(", ")"):
(isoCode=s)||(isoCode=a)
&&
title=s
&&
(ti=2)&&(t=2)
||
t=2&&e>5
Can it be done? I know I can do it with substring (removing first and last character), but I want to know if it can be done with regex.
Upvotes: 1
Views: 761
Reputation: 626826
You may use
\((?<R>(?>\((?<DEPTH>)|\)(?<-DEPTH>)|[^()]+)*(?(DEPTH)(?!)))\)|(?<R>&&|\|\|)
See the regex demo, grab Group "R" value.
Details
\(
- an open (
(?<R>
- start of the R
named group:
(?>
- start of the atomic group:
\((?<DEPTH>)|
- an open (
and an empty string is pushed on the DEPTH
group stack or\)(?<-DEPTH>)|
- a closing )
and an empty string is popped off the DEPTH
group stack or[^()]+
- 1+ chars other than (
and )
)*
- zero or more repetitions(?(DEPTH)(?!))
- a conditional construct that checks if the number of close and open parentheses is balanced)
- end of R
named group\)
- a closing )
|
- or(?<R>&&|\|\|)
- another occurrence of Group R
matching either of the 2 subpatterns:
&&
- a &&
substring|
- or\|\|
- a ||
substring.C# code:
var pattern = @"\((?<R>(?>\((?<DEPTH>)|\)(?<-DEPTH>)|[^()]+)*(?(DEPTH)(?!)))\)|(?<R>&&|\|\|)";
var results = Regex.Match(input, pattern)
.Cast<Match>()
.Select(m => m.Groups[1].Value)
.ToList();
Upvotes: 4
Reputation: 22817
You can use the regex below, but I'd still strongly suggest you write a proper parser for this instead of using regex.
\(((?>\((?<DEPTH>)|\)(?<-DEPTH>)|.?)*(?(DEPTH)(?!)))\)|&{2}|\|{2}
using System;
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
string input = "((isoCode=s)||(isoCode=a))&&(title=s)&&((ti=2)&&(t=2))||(t=2&&e>5)";
string pattern = @"\(((?>\((?<DEPTH>)|\)(?<-DEPTH>)|.?)*(?(DEPTH)(?!)))\)|&{2}|\|{2}";
MatchCollection matches = Regex.Matches(input, pattern);
foreach (Match match in matches)
{
Console.WriteLine(match.Groups[1].Success ? match.Groups[1].Value : match.Groups[0].Value);
}
}
}
(isoCode=s)||(isoCode=a)
&&
title=s
&&
(ti=2)&&(t=2)
||
t=2&&e>5
Upvotes: 1