在PHP中拆分嵌套括号的正确方法,例如;根[1[a,b,c],2[d,e,f]];进入阵列?

在PHP中拆分嵌套括号的正确方法,例如;根[1[a,b,c],2[d,e,f]];进入阵列?,php,arrays,regex,parsing,split,Php,Arrays,Regex,Parsing,Split,正如标题所说,我正在寻找一种健壮的方法将这个表达式解析为数组(代码中的示例) 我试图通过正则表达式来实现,但由于括号和逗号是嵌套的,所以无法产生正确的结果。我该怎么做呢?根据@Rizier123的建议,这里是我能够创建的代码 <?php $str = 'root[one[a,b,c],two[d,e,f]]'; $str = preg_replace('/\[/', '=> [', $str); $str = preg_replace('/(\w+)/', "'\\1'", $st

正如标题所说,我正在寻找一种健壮的方法将这个表达式解析为数组(代码中的示例)


我试图通过正则表达式来实现,但由于括号和逗号是嵌套的,所以无法产生正确的结果。我该怎么做呢?

根据@Rizier123的建议,这里是我能够创建的代码

<?php

$str = 'root[one[a,b,c],two[d,e,f]]';
$str = preg_replace('/\[/', '=> [', $str);
$str = preg_replace('/(\w+)/', "'\\1'", $str);

eval("\$code = [$str];");
print "<pre>"; print_r($code); exit;

下面的一个简单解析器应该可以完成这项工作。我并没有对它进行太多的测试——只测试了一条成功的路线,并且基于公平的假设,没有几个明显的边缘案例

var_dump(parse('root[one[a,b,c],two[d,e,f]]);
函数解析($str,$level=0){
如果($level==0){
//为简单起见,只需一次剥离空间
$str=str\u替换([“”,“\t”],“”,$str);
}
$result=[];
while(true){
$rest=strpbrk($str,[],');
如果(!$rest){
如果(strlen($str)>0){
抛出新的ExpectedDofString异常($str);
}
返回$result;
}
$term=substr($rest,0,1);
$rest=substr($rest,1);
$val=substr($str,0,strpos($str,$term));
转换($期限){
案例“[”:
如果(!$val){
$val=0;
}elseif(isset($result[$val])){
抛出新的非UniqueKeyException($val);
}
列表($a,$str)=解析($rest,$level+1);
if(is_null($a)和&is_null($str)){
抛出新括号smatchexception($rest);
}
$result=array_merge($result,[$val=>$a]);
打破
案例']':
如果($val){
$result[]=$val;
}
如果($1级以下){
抛出新括号smatchexception($rest);
}
if(strlen($rest)>0&&!在_数组中(substr($rest,0,1),[',',']'])){
抛出新的畸形字符串异常($val.$term.$rest);
}
返回[$result,ltrim($rest,',')];
案例',':
如果(!$val){
抛出新的意外ComaException($term.$rest);
}
$result[]=$val;
$str=$rest;
打破
违约:
抛出新的LogicException();
}
}
}


您将需要实现所有异常类,但它应该很简单。否则,只需将它们替换为泛型
\Exception()

使其成为有效的JSON,您只需使用
JSON\u decode()
hi,谢谢您的建议。。它确实出现在我的脑海中,因为表达式看起来像JSON,但不幸的是,在JSON_decode对其进行解析之前,必须对其进行大量修改。。我可以尝试一下,但是你认为用这种方法是最好的吗?这可能是最简单的方法,所以我会尝试一下,当你陷入困境时,在这里发布当前的进展,我们会帮助你。永远不要使用正则表达式来解析某些东西@Rizier123:我能够创建一个PHP数组,但无法找到将其转换为json的方法(因为json同时使用方括号和花括号,所以无法找到如何正确替换它们的方法)。。你能帮我用json_decode写同样的代码吗?不幸的是,它使用了
eval
,所以如果有人有更好的想法,我还是洗耳恭听。。谢谢这太棒了。。最好的一点是,如果有一天语法发生了变化(大括号,等等),那么应该很容易适应这些变化(其他方法可能不可能)。
$decoded = ['root' => ['one' => ['a', 'b', 'c'], 'two' => ['d', 'e', 'f']]
<?php

$str = 'root[one[a,b,c],two[d,e,f]]';
$str = preg_replace('/\[/', '=> [', $str);
$str = preg_replace('/(\w+)/', "'\\1'", $str);

eval("\$code = [$str];");
print "<pre>"; print_r($code); exit;
var_dump(parse('root[one[a,b,c],two[d,e,f]]'));

function parse($str, $level = 0) {
    if ($level === 0) {
        // strip spaces once for simplicity
        $str = str_replace([" ", "\t"], '', $str);
    }
    $result = [];
    while(true) {
        $rest = strpbrk($str, '[],');
        if (!$rest) {
            if (strlen($str) > 0) {
                throw new ExpectedEndOfStringException($str);
            }
            return $result;
        }
        $term = substr($rest, 0, 1);
        $rest = substr($rest, 1);
        $val = substr($str, 0, strpos($str, $term));
        switch ($term) {
            case '[':
                if (!$val) {
                    $val = 0;
                } elseif (isset($result[$val])) {
                    throw new NonUniqueKeyException($val);
                }
                list($a, $str) = parse($rest, $level+1);
                if (is_null($a) && is_null($str)) {
                    throw new BracketsMismatchException($rest);
                }
                $result = array_merge($result, [$val => $a]);
                break;
            case ']':
                if ($val) {
                    $result[] = $val;
                }
                if($level < 1) {
                    throw new BracketsMismatchException($rest);
                }
                if (strlen($rest) > 0 && !in_array(substr($rest, 0, 1), [',', ']'])) {
                    throw new MalformedStringException($val.$term.$rest);
                }
                return [$result, ltrim($rest, ',')];
            case ',':
                if (!$val) {
                    throw new UnexpectedComaException($term.$rest);
                }
                $result[] = $val;
                $str = $rest;
                break;
            default:
                throw new LogicException();
        }
    }
}