相当于preg_match,返回漂亮(多维)数组

时间:2014-09-18 12:39:25

标签: php regex multidimensional-array

是否有一些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 个答案:

答案 0 :(得分:0)

有趣的问题!内置没有这样的东西,你必须捕获匹配的偏移量,并且每次匹配检查它的偏移是否在其他边界内:这让我想起了嵌套集模型:

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
                                                                )

                                                        )

                                                )

                                        )

                                )

                        )

                )

        )

)