Skip to content
Advertisement

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….

Advertisement

Answer

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

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement