preg_match搜索

<?php
$content = "
{php
    {php 1 php}
    {php 2 php}
    {php 3 php}
php}"; 

How I can get 4 strings?

First:

{php 1 php}
{php 2 php}
{php 3 php}

Second:

1

Third:

2

Four:

3

While you could easily parse such input with a simple counter, it is possible to use a recursive regex to get what you want. A simple (?) regex to validate the input would be:

^({php\s*(\d+|(?1)+)\s*php}\s*)$

(?1) is a recursive match, it tries to match the first group again, which is another {php ... php} token. We also have a capturing group between the phps to capture their content.

In your case you want to capture overlapping results (in fact, even results contained within other results). This is even less pretty, but still possible, using a look-ahead. Look-around can have capturing groups, so the pattern would be:

(?=({php\s*(\d+|(?1)+)\s*php}\s*))

The result has a two extra captured groups - blank results for the look around, and the whole token with the outer {php ... php}, but if you use PREG_PATTERN_ORDER your expected results will be on the third postion ([2]):

[2] => Array
(
    [0] => {php 1 php}
           {php 2 php}
           {php 3 php}
    [1] => 1
    [2] => 2
    [3] => 3
)

Here's a bit more complex example: http://ideone.com/sWWrT

Now, the mandatory word of caution. As I've said earlier, this is much more readable and maintainable with a simple depth counter, you don't really need a regex here, beyond recreational use.

$regex = preg_match_all("/({php (\d+) php})+/", $content);
$regex[0][0] == "{php 1 php}";
$regex[0][1] == "{php 2 php}";
$regex[0][2] == "{php 3 php}";
end($regex)[0] == "1";
end($regex)[1] == "2";
end($regex)[2] == "3";

Looking for something like this?