Разведывать строку, кроме окружения круглыми скобками?

Я пытаюсь взорвать строку по вертикальным барам. Это легкая часть. Тем не менее, я НЕ хочу, чтобы раскол влиял на подстроки, окруженные скобками. Это означает, что мне нужна строка, такая как:

Hello (sir|maam).|Hi there! 

взорваться:

 Array ( [0] => Hello (sir|maam). [1] => Hi there! ) 

Используя обычную функцию разрыва, я не верю, что есть способ сказать ей игнорировать этот бар, окруженный скобками. Однако у меня есть некоторые идеи.

Я знаю, что это можно было бы сделать, просто взорвав строку, а затем перейдя через массив и объединив все между строками, которые содержат ( к закрывающей строке, которая содержит ) . Тем не менее, я чувствую, что должен быть более элегантный способ достижения этого.

Я прав? Есть ли менее интенсивные кодовые средства для разделения строки на массив с учетом этих ограничений?

Если вы можете гарантировать, что скобки будут сбалансированы и никогда не вложены (то есть, если никогда не будет 'Oops(!' Или '(nested stuff (like this)|oops)' , и никогда не будет || вне круглых скобок, которые вы хотите сопоставить как пустую строку, тогда это должно помочь:

 preg_match_all('/(?:[^(|]|\([^)]*\))+/', $your_string, $matches); $parts = $matches[0]; 

Он будет соответствовать [либо (символ, который не является | или ( ), либо ( и ) охватывающий все, что не является ) (который включает | )], сколько раз (возможно, хотя бы один раз). Короткая версия: это сделает | между скобками части матча, а не разделителем.

Другая возможность, которая немного менее загадочна:

 $parts = preg_split('/\|(?![^(]*\))/', $your_string); 

Использует предварительное утверждение о дисквалификации любых | за ним следует a ) если нет ( в промежутке между ними. Все еще немного неумолимо о parens, но он будет соответствовать пустым строкам между двумя | s.

Пока кто-то не напишет решение на основе регулярного выражения, которое, я сомневаюсь, возможно за один проход, это должно сработать. Это простой перевод требований к коду.

 <?php function my_explode($str) { $ret = array(); $in_parenths = 0; $pos = 0; for($i=0;$i<strlen($str);$i++) { $c = $str[$i]; if($c == '|' && !$in_parenths) { $ret[] = substr($str, $pos, $i-$pos); $pos = $i+1; } elseif($c == '(') $in_parenths++; elseif($c == ')') $in_parenths--; } if($pos > 0) $ret[] = substr($str, $pos); return $ret; } $str = "My|Hello (sir|maam).|Hi there!"; var_dump(my_explode($str));