Regex to split words containing brackets based on group

Viewed 98

I have the following terms which are considered in a group. Create Set and Delete.

For the below input

Create(Apple | Banana(Tree) | Mango (Tree) ) | Delete(Guava)|Set(Orange(Tree))

the expected split should be as follows

Create(Apple | Banana(Tree) | Mango (Tree) )
Delete(Guava)
Set(Orange(Tree))

I could come up with the following regex which is not giving the correct split.

(Create|Set|Delete)\(.*\)\s*\|
2 Answers

What if you use:

\s*\|\s*(?=\b(?:Create|Set|Delete)\b)

See the online demo


  • \s*\|\s* - A literal pipe-symbol surrounded by zero or more spaces (greedy).
  • (?= - Positive lookahead:
    • \b - Word-boundary.
    • (?: - Open non-capturing group:
      • Create|Set|Delete - Match either of these alternatives literally.
      • ) - Close non-capturing group.
    • \b - Word-boundary.
    • ) - Close positive lookahead.

Note: Just add the other "Associate" and "Disassociate" as alternatives as per your own attempt.


In c# code:

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\s*\|\s*(?=\b(?:Create|Set|Delete)\b)";
      string input = "Create(Apple | Banana(Tree) | Mango (Tree) ) | Delete(Guava)|Set(Orange(Tree))";
      string[] result = Regex.Split(input, pattern, 
                                    RegexOptions.IgnoreCase,
                                    TimeSpan.FromMilliseconds(500));
      for (int ctr = 0; ctr < result.Length; ctr++) {
         Console.Write("'{0}'", result[ctr]);
         if (ctr < result.Length - 1) 
            Console.Write(", ");
      }
      Console.WriteLine();
   }
}

Outputs:

'Create(Apple | Banana(Tree) | Mango (Tree) )', 'Delete(Guava)', 'Set(Orange(Tree))'

Try it over here.

You can use balanced construct:

\b(?:Create|Set|Delete)\((?>[^()]+|(?<c>)\(|(?<-c>)\))*(?(c)(?!))\)

See the .NET regex demo.

Details

  • \b - a word boundary
  • (?:Create|Set|Delete) - one of the alternatives listed in the non-capturing group
  • \( - a ( char
  • (?>[^()]+|(?<c>)\(|(?<-c>)\))* - zero or more occurrences of any one or more chars other than ( and ) (see [^()]+), or a ( char (with an empty value pushed onto Group "c" stack), or a ) char (with a value popped from the Group "c" stack), then
  • (?(c)(?!)) - a conditional failing the match if Group "c" stack is not empty
  • \) - a ) char.

See the C# demo:

var reg = @"\b(?:Create|Set|Delete)\((?>[^()]+|(?<c>)\(|(?<-c>)\))*(?(c)(?!))\)";
var text = "Create(Apple | Banana(Tree) | Mango (Tree) ) | Delete(Guava)|Set(Orange(Tree))";
var result = Regex.Matches(text, reg).Cast<Match>().Select(x => x.Value).ToList();
foreach (var s in result)
    Console.WriteLine(s);

Output:

Create(Apple | Banana(Tree) | Mango (Tree) )
Delete(Guava)
Set(Orange(Tree))
Related