Эквивалент preg_match, который возвращает симпатичный (многомерный) массив

Есть ли какая-нибудь функция или библиотека 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"}

Каждый результат подвыражения находится в ожидаемой (требуемой) глубине в этом массиве.

1

Решение

Интересный вопрос! Нет такой встроенной функции, вам нужно будет фиксировать смещения совпадений и для каждого совпадения проверять, находится ли его смещение в границах каких-то других: что напоминает мне модель вложенных множеств:

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
)

)

)

)

)

)

)

)

)
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]