PHP: podzielony ciąg na przecinek, ale NIE w nawiasach klamrowych lub cudzysłowach?
W PHP mam następujący ciąg:
$str = "AAA, BBB, (CCC,DDD), 'EEE', 'FFF,GGG', ('HHH','III'), (('JJJ','KKK'), LLL, (MMM,NNN)) , OOO";
Muszę podzielić ten ciąg na następujące części:
AAA
BBB
(CCC,DDD)
'EEE'
'FFF,GGG'
('HHH','III')
(('JJJ','KKK'),LLL, (MMM,NNN))
OOO
Próbowałem kilku wyrażeń regularnych, ale nie mogłem znaleźć rozwiązania. Jakieś pomysły?
AKTUALIZACJA
Zdecydowałem, że użycie regex nie jest najlepszym rozwiązaniem, gdy mamy do czynienia ze zniekształconymi danymi, cudzysłowami, itp.
Dzięki sugestiom przedstawionym tutaj znalazłem funkcję, która używa parsowania, którą przepisałem do własnych potrzeb. Może obsługiwać różnego rodzaju nawiasy, a separator i cytat są również parametrami.
function explode_brackets($str, $separator=",", $leftbracket="(", $rightbracket=")", $quote="'", $ignore_escaped_quotes=true ) {
$buffer = '';
$stack = array();
$depth = 0;
$betweenquotes = false;
$len = strlen($str);
for ($i=0; $i<$len; $i++) {
$previouschar = $char;
$char = $str[$i];
switch ($char) {
case $separator:
if (!$betweenquotes) {
if (!$depth) {
if ($buffer !== '') {
$stack[] = $buffer;
$buffer = '';
}
continue 2;
}
}
break;
case $quote:
if ($ignore_escaped_quotes) {
if ($previouschar!="\\") {
$betweenquotes = !$betweenquotes;
}
} else {
$betweenquotes = !$betweenquotes;
}
break;
case $leftbracket:
if (!$betweenquotes) {
$depth++;
}
break;
case $rightbracket:
if (!$betweenquotes) {
if ($depth) {
$depth--;
} else {
$stack[] = $buffer.$char;
$buffer = '';
continue 2;
}
}
break;
}
$buffer .= $char;
}
if ($buffer !== '') {
$stack[] = $buffer;
}
return $stack;
}