Splitting Strings Containing Paired Brackets

Learn how to split a string containing pair brackets.

Suppose we have the input text provided below:

($one, $two, ($string .")" )), $three, hello,
"(this", "that )", $end($one, ($two))

And that we would like to split it into the array of strings as shown below:

array:6 [
  0 => "($one, $two, ($string .")" ))"
  1 => " $three"
  2 => " hello"
  3 => """
    
    "(this"
    """
  4 => " "that )""
  5 => " $end($one, ($two))"
]

However, if the entire input text is surrounded in parentheses, as shown below:

(($one, $two, ($string .")" )), $three, hello,
"(this", "that )", $end($one, ($two)))

We want to produce an array containing only a single value, which would be the input string:

array:1 [
  0 => """
    (($one, $two, ($string .")" )), $three, hello,
    "(this", "that )", $end($one, ($two)))
    """
]

At first, this might seem like an incredibly complex problem to solve. However, if we analyze our expected output carefully, we can see that we are not splitting a substring if it is contained within a balanced set of parentheses. Additionally, we ignore any parenthesis that appears within a single- or double-quoted string. Instead of trying to engineer an overly complicated pattern-matching solution, we can reduce our problem to a simple counting problem.

Suppose we were to keep a running count that increments every time we see opening parentheses and decrements it when we encounter a valid closing parenthesis. In that case, we can use the more straightforward counter to complete our task because the counter will equal zero when we have assembled a valid parentheses pair, regardless of how many nested pairs appear.

Implementing the PairedBracketCursor class

Let’s take a look at how we could implement this using our cursor concept in the code below:

Get hands-on with 1400+ tech skills courses.