Ну, есть несколько подходов к этой проблеме. Один из способов - захватить элементы, которые вы хотите исключить, найти их смещения и длины и, в основном, просто извлечь эти части из исходной строки, и все, что вам осталось, это части вне тегов.
Вот функция в качестве примера:
<?php
function match_all_except ($pattern, $string)
{
preg_match_all($pattern, $string, $match, PREG_OFFSET_CAPTURE);
$parts = array();
$pos = 0;
foreach ($match[0] as $info)
{
$parts[] = substr($string, $pos, $info[1] - $pos);
$pos = $info[1] + strlen($info[0]);
}
$parts[] = substr($string, $pos);
return $parts;
}
$string = 'one<? foo ?>two<? bar ?>three';
$parts = match_all_except('/<\?.*?\?>/s', $string);
// Will output "one, two, three, "
foreach ($parts as $outside)
{
echo "$outside, ";
}
?>
В качестве альтернативы, вы можете использовать это регулярное выражение /\G(?=.)((?:(?!<\?).)*)(?:<\?((?!\?>).)*(\?>|$)|$)/s
в preg_match_all
, чтобы захватить все части вне тегов в одну подматрицу. Хотя это может иметь свои собственные трудности, если теги не совпадают в документе равномерно.
Например,
<?php
$string = 'one<? foo ?>two<? bar ?>three';
preg_match_all('/\G(?=.)((?:(?!<\?).)*)(?:<\?((?!\?>).)*(\?>|$)|$)/s', $string, $match);
// Will output "one, two, three, "
foreach ($match[1] as $outside)
{
echo "$outside, ";
}
?>