Reputation: 477
I need to split text by pipe that is not in brackets. Here is the sample text
I {need|want|{ask|prefer}} you to {help {Jason|Maria|Santa|{Lucia|Raul}'s father}|go to school}
I have found this /\|(?![^{]*})/g
here: regex, extract string NOT between two brackets
now when i want to split this part of string by pipe
help {Jason|Maria|Santa|{Lucia|Raul}'s father}|go to school
it also selects pipes between Jason, Maria, Santa because there is an opening bracket after them. How to change regex to match only pipe if it's not in any of the brackets.
test strings:
help {Jason|Maria|Santa|{Lucia|Raul}'s father}|go to school
should return
help {Jason|Maria|Santa|{Lucia|Raul}'s father}
go to school
.
Jason|Maria|Santa|{Lucia|Raul}'s father
should return
Jason
Maria
Santa
{Lucia|Raul}'s father
Upvotes: 2
Views: 222
Reputation: 627517
You may use a SKIP-FAIL regex:
'~(\{(?:[^{}]++|(?1))*})(*SKIP)(*F)|\|~'
See the regex demo
Details
(\{(?:[^{}]++|(?1))*})(*SKIP)(*F)
- match a substring that is between balanced curly braces and skip this match
(\{(?:[^{}]++|(?1))*})
- Capturing group 1 matching {
, then 0+ repetitions of 1+ chars other than {
and }
or the whole Group 1 pattern is recursed ((?1)
is a regex subroutine), and then }
(balanced curly braces substring)(*SKIP)(*F)
- the PCRE verbs that make the regex engine fail the match and skip the matched text to proceed matching from the match end|
- or\|
- match a literal pipe to split with.$re = '~(\{(?:[^{}]++|(?1))*})(*SKIP)(*F)|\|~';
$str = "Jason|Maria|Santa|{Lucia|Raul}'s father";
print_r( preg_split($re, $str) );
Output:
Array
(
[0] => Jason
[1] => Maria
[2] => Santa
[3] => {Lucia|Raul}'s father
)
Upvotes: 3