0

hello i have 2 parent (or more ...) block and many child blocks inside them.

Block1 {

    blockchild1 {

    }

    blockchild2 {

    }

    , ...
}

Block2 {

    blockchild1 {

    }

    blockchild2 {

    }

    , ...
}

i want to use php regex and get first all parents blocks inside

([a-z-0-9]*)\s*[{](.*?)[}]

but this regex stop when arrive to first childblock close } means first data receive is

Block1 {

    blockchild1 {

    }

but i want to get some thing like this

array 1 = Block1
array 2 = blockchild1 {

    }

    blockchild2 {

    }

    , ...

i want the regex pass child blocks [}] and get everything inside of parents block. my regex is PCRE (PHP)

Elh48
  • 43
  • 8

3 Answers3

0

Try this:

$str = 'Block1 {

    block1child1 {

    }

    block1child2 {

    }

    block1child3 {

    }
}

Block2 {

    block2child1 {

    }

    block2child2 {

    }

}';

$sub = '(\s*[a-z-0-9]*\s*{.*?}\s*)*';
preg_match_all("/([a-z-0-9]*)\s*{($sub)}/sim", $str, $matches, PREG_SET_ORDER);

var_dump($matches);

I used the variable $sub to clarify the approach. It returns:

$matches[0][1] = 'Block1';
$matches[0][2] = '



block1child1 {



}



block1child2 {



}



block1child3 {



}

';

It contains the right output for Block2 (index 1 of $matches). This regexp does not work with nested blocks in child blocks and does not work with any other content inside parent blocks except blocks. But you have not mentioned any of this.

Here is online version.

rNix
  • 2,457
  • 1
  • 22
  • 28
0
$str = 'Block1 {

    block1child1 {

    }

    block1child2 {

    }

    block1child3 {

    }
}

Block2 {

    block2child1 {

    }

    block2child2 {

    }

}';

$str = preg_replace('([\w\d]+)', '"$0"', $str);
$str = str_replace(' {', ': {', $str);
$str = str_replace('}', '},', $str);
$str = preg_replace('/\}\,[.\n]*?}/', '}}', $str);


$str =  json_decode('{' . substr($str, 0, strlen($str) - 1)  . '}', true);

var_export($str);

array (
  'Block1' => 
  array (
    'block1child1' => 
    array (
    ),
    'block1child2' => 
    array (
    ),
    'block1child3' => 
    array (
    ),
  ),
  'Block2' => 
  array (
    'block2child1' => 
    array (
    ),
    'block2child2' => 
    array (
    ),
  ),
)
  1. Convert string to JSON
  2. Convert JSON to array
0

You need to use a recursive pattern:

$pattern = '~(\w+)\s*{([^{}]*(?:{(?2)}[^{}]*)*)}~';

details:

~ # delimiter
(\w+) # capture group 1: block name
\s* # eventual whitespaces
{
(   # capture group 2
    [^{}]* # all that isn't a curly bracket
    (?:
        { (?2) } # reference to the capture group 2 subpattern
        [^{}]*
    )*
)
}
~

Note that the reference to the capture group 2 is inside the capture group 2 itself, that's why the pattern is recursive.

Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125