在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();
}
}
}