Есть ли какая-нибудь функция или библиотека PHP, которая возвращает результат регулярного выражения в виде довольно многомерного массива в соответствии с скобками в регулярном выражении? Это то, что я имею в виду:
preg_match('/(n(e?)c)(o)/', 'neco', $vysl);
var_dump($vysl);
возвращает это:
array(4) {
[0]=>
string(4) "neco"[1]=>
string(3) "nec"[2]=>
string(1) "e"[3]=>
string(1) "o"}
Я хотел бы иметь вывод, как это:
array(3) {
[0]=>
string(4) "neco"[1]=>
array(2) {
[0]=>
string(3) "nec"[1]=>
string(1) "e"}
[2]=>
string(1) "o"}
Каждый результат подвыражения находится в ожидаемой (требуемой) глубине в этом массиве.
Интересный вопрос! Нет такой встроенной функции, вам нужно будет фиксировать смещения совпадений и для каждого совпадения проверять, находится ли его смещение в границах каких-то других: что напоминает мне модель вложенных множеств:
function match_tree($re, $subject) {
preg_match($re, $subject, $ms, PREG_OFFSET_CAPTURE);
$p = [(object)[]];
foreach($ms as $m) {
$m = (object) [
'le' => $m[1],
'ri' => $m[1] + strlen($m[0]) - 1,
'str' => $m[0]];
for($i = count($p) - 1; $i >= 0; $i--) {
if(!$i || ($m->le >= $p[$i]->le && $m->le <= $p[$i]->ri)) {
$p []= $m;
$p[$i]->sub []= $m;
break;
}
}
}
return $p[0];
}
Например,
print_r(match_tree('/(n(e?)c)(o)(f(o(abc)))/', 'XnecofoabcY'));
возвращается
stdClass Object
(
[sub] => Array
(
[0] => stdClass Object
(
[le] => 1
[ri] => 9
[str] => necofoabc
[sub] => Array
(
[0] => stdClass Object
(
[le] => 1
[ri] => 3
[str] => nec
[sub] => Array
(
[0] => stdClass Object
(
[le] => 2
[ri] => 2
[str] => e
)
)
)
[1] => stdClass Object
(
[le] => 4
[ri] => 4
[str] => o
)
[2] => stdClass Object
(
[le] => 5
[ri] => 9
[str] => foabc
[sub] => Array
(
[0] => stdClass Object
(
[le] => 6
[ri] => 9
[str] => oabc
[sub] => Array
(
[0] => stdClass Object
(
[le] => 7
[ri] => 9
[str] => abc
)
)
)
)
)
)
)
)
)
Других решений пока нет …