'How can I convert from a{a{} b{}} to a[a[],b[]] using php preg_match?

Group test
{
    Group test1
    {
        #-# Type    Val
        1   typ1    10
        2   typ2    10
        3   typ3    10
    }
    
    Group test2
    {
        #-# Type    Val
        1   typ1    10
        2   typ2    10
    }
}

How can I convert the above structure to the following result.

$result=[
    "test"=>[
        "test1"=>[
            0=>["#-#","Type","Val"],
            1=>["1","typ1","10"],
            2=>["1","typ1","10"],
            3=>["1","typ1","10"]
        ],
        "test2"=>[
            0=>["#-#","Type","Val"],
            1=>["1","typ1","10"],
            2=>["1","typ1","10"]
        ]
    ]
];

I tried many patterns, but failed.

I tried with regex pattern and explode function. I Failed in Recursive function. I want to get the output as array or json. How can i do it.Thanks....



Solution 1:[1]

An approach in two steps: the first checks the whole string syntax with a recursive pattern, if this one is correct, then the second step parse the string with a recursive function.

$str = <<<'STR'
Group test
{
    Group test1
    {
        #-# Type    Val
        1   typ1    10
        2   typ2    10
        3   typ3    10
    }
    
    Group test2
    {
        #-# Type    Val
        1   typ1    10
        2   typ2    10
    }
}
STR;

$pattern = <<<'REGEX'
~
(?(DEFINE)
    (?<group>
        Group \s+ \g<groupName> \s* { \s*
            (?:
                \g<group> (?: \s+ \g<group>)*
              |
                \g<line> (?: \h*+ \s+ \g<line> )*
            )?
            \s*
        } 
    )
    
    (?<groupName> \w+ )
    (?<line> \g<value> (?: \h+ \g<value>)* )
    (?<value> [^\s{}]+ )
)

\A \s* \g<group> \s* \z (*:MAIN_GROUP) 
~x
REGEX;

function group2array($group) {
    $ret = [];
    $index = 0;
    
    // this pattern extracts the group name and the group content
    preg_match(
        '~Group \s+ (?<name> \w+ ) \s* { \s* (?<content> .* \S ) \s* } ~sx',
        $group, $match
    );
    $name = $match['name'];
    $content = $match['content'];
    
    $ret[$name] = [];
    
    preg_match_all( // this one extracts groups or lines of values
        '~
           \s* (?<group> Group \s+ \w+ \s* { [^{}]*+ (?: \g<group> [^{}]* )*+ } )
          | 
           \s* (?<line> [^\s{}]+ (?: \h+ [^\s{}]+ )* )
        ~x',
        $content, $matches, PREG_SET_ORDER
    );
    
    foreach($matches as $m) {
        if (isset($m['line'])) {
            $ret[$name][$index++] = preg_split('~\s+~', $m['line']);
        } else {
            $group = group2array($m['group']);
            $ret[$name][key($group)] = current($group);
        }
    }
        
    return $ret;
}
    
if ( preg_match($pattern, $str) ) { // check the string syntax before parsing
    $result = group2array($str);
    echo json_encode($result), PHP_EOL,
         print_r($result, true), PHP_EOL;
}

demo

Solution 2:[2]

I did a study in this way, but it was not enough. some array data is empty

<pre>
<?php 
$data=[];
$number=[];
$temp=null;
$op=stream_context_create(array("ssl"=>array("verify_peer"=>false,"verify_peer_name"=>false)));
$f1=file_get_contents('https://huc.re/data.txt',false,$op);
$f2=preg_split('/\r|\n/si', $f1);
foreach($f2 as $k=>$f3){
    $ilk_karakter = substr($f3 , 0 , 1);
    if($ilk_karakter != "#"){
        if(strstr($f3,"{")){
            if($f3=="{"){
                $last=$k-1;
                $g=trim(str_replace("Group","",$f2[$last]));
                $data[$g]=null;
            }
        }elseif(strstr($f3,"}")){
            if($f3=="}"){
                unset($last);
            }
        }else{
            if(isset($last)){
                $data[$g].=$f3.PHP_EOL;
            }
        }
    }
}
//STEP 2
foreach($data as $k1=>$d1){
    $ff2=preg_split('/\r|\n/si', $d1);
    if(strstr($d1,"Group")){
        $data[$k1]=[];
        foreach($ff2 as $k=>$f3){
            if(strstr($f3," Group") and !strstr($f3,"       Group")){
                $last=$k;
                if(isset($ff2[$last])){
                    $g=str_replace("%","",rawurlencode(utf8_decode(trim(str_replace("Group","",$ff2[$last])))));
                    if(trim($f3) != ""){
                        $data[$k1][$g]=null;
                    }
                }
            }else{
                if(trim($f3) != ""){
                    $data[$k1][$g].=$f3.PHP_EOL;
                }
            }
        }
    }else{
        $data[$k1]=[];
        for($x=0;$x<count($ff2);$x++){
            $a=explode("    ",$ff2[$x]);
            if(count($a)>3){
                if(trim($ff2[$x]) != ""){
                    $b=array_values(array_filter($a));
                    $data[$k1][$x]=$b;
                }
            }
        }
        $data[$k1]=array_values($data[$k1]);
    }
}
//STEP 3
foreach($data as $k1=>$d1){
    foreach($d1 as $k2=>$d2){
        if(!is_array($d2)){
            $ff2=preg_split('/\r|\n/si', $d2);
            if(strstr($d2,"Group")){
                $data[$k1][$k2]=[];
                foreach($ff2 as $k=>$f3){
                    if(strstr($f3,"     Group") and !strstr($f3,"   Group")){
                        $last=$k;
                        if(isset($ff2[$last])){
                            $g=str_replace("%","",rawurlencode(utf8_decode(trim(str_replace("Group","",$ff2[$last])))));
                            if(trim($f3) != ""){
                                $data[$k1][$k2][$g]=null;
                            }
                        }
                    }else{
                        if(trim($f3) != ""){
                            if(isset($data[$k1][$k2][$g])){
                                $data[$k1][$k2][$g].=$f3.PHP_EOL;
                            }
                        }
                    }
                }
            }else{
                $data[$k1][$k2]=[];
                for($x=0;$x<count($ff2);$x++){
                    $a=explode("    ",$ff2[$x]);
                    if(count($a)>3){
                        if(trim($ff2[$x]) != ""){
                            $b=array_values(array_filter($a));
                            $data[$k1][$k2][$x]=$b;
                        }
                    }
                }
                $data[$k1][$k2]=array_values($data[$k1][$k2]);
            }
        }
    }
}
print_r($data);

?>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Casimir et Hippolyte
Solution 2