It is possible! You can have each level of content using a recursive regular expression:
$data = <<<LOD
{{START1}}
aaaaa
{{START2}}
bbbbb
{{START3}}
ccccc
{{START4}}
ddddd
{{END4}}
{{END3}}
{{END2}}
{{END1}}
LOD;
$pattern = '~(?=({{START\d+}}(?>[^{]++|(?1))*{{END\d+}}))~';
preg_match_all ($pattern, $data, $matches);
print_r($matches);
explanations:
part: ({{START\d+}}(?>[^{]++|(?1))*{{END\d+}})
This part of the pattern describe a nested structure with {{START#}}
and {{END#}}
( # open the first capturing group
{{START\d+}}
(?> # open an atomic group (= backtracks forbidden)
[^{]++ # all that is not a { one or more times (possessive)
| # OR
(?1) # refer to the first capturing group itself
) # close the atomic group
{END\d+}} #
) # close the first capturing group
Now the problem is that you can't capture all the level with this part only, because all the characters of the string are consumed by the pattern. In other words you can't match overlapped parts of the string.
The issue is to wrap all this part inside a zero-width assertion which doesn't consume characters like a lookahead (?=...)
, result:
(?=({{START\d+}}(?>[^{]++|(?1))*{{END\d+}}))
This will match all the levels.