Я пришел сюда со сложной проблемой разделения строк, подобной этой, но ни один из ответов здесь не сделал именно то, что я хотел - поэтому я написал свой.
Я публикую это здесь на всякий случай, если это будет полезно кому-то еще.
Это, вероятно, очень медленный и неэффективный способ сделать это - но он работает для меня.
function explode_adv($openers, $closers, $togglers, $delimiters, $str)
{
$chars = str_split($str);
$parts = [];
$nextpart = "";
$toggle_states = array_fill_keys($togglers, false); // true = now inside, false = now outside
$depth = 0;
foreach($chars as $char)
{
if(in_array($char, $openers))
$depth++;
elseif(in_array($char, $closers))
$depth--;
elseif(in_array($char, $togglers))
{
if($toggle_states[$char])
$depth--; // we are inside a toggle block, leave it and decrease the depth
else
// we are outside a toggle block, enter it and increase the depth
$depth++;
// invert the toggle block state
$toggle_states[$char] = !$toggle_states[$char];
}
else
$nextpart .= $char;
if($depth < 0) $depth = 0;
if(in_array($char, $delimiters) &&
$depth == 0 &&
!in_array($char, $closers))
{
$parts[] = substr($nextpart, 0, -1);
$nextpart = "";
}
}
if(strlen($nextpart) > 0)
$parts[] = $nextpart;
return $parts;
}
Использование выглядит следующим образом. explode_adv
принимает 5 аргументов:
- Массив символов, открывающих блок - например,
[
, (
и т. Д.
- Массив символов, которые закрывают блок - например,
]
, )
и т. Д.
- Массив символов, которые переключают блок - например,
"
, '
и т. Д.
- Массив символов, который должен вызвать разбиение на следующую часть.
- Строка для работы.
Этот метод, вероятно, имеет недостатки - правка приветствуется.