块内部匹配块与pcre

时间:2018-02-04 03:51:42

标签: php regex pcre

this regex101 demo中,我试图获取每个块的内容:

{% block works %}
    This works
{% endblock %}

{% block main_block %}
    {% block sub_block %}
        Does not work
    {% endblock %} #ends here
    This is not covered
{% endblock %}

如果块内部没有块,它可以正常工作,但是,在第二个块(main_block)中,它无法匹配其所有内容,因为在内部找到了一个块。

我需要一个捕获main_block和sub_block块的正则表达式模式,而不会在第一个{%endblock%}标记上结束。

现在,我的表达式如下:\{\%\s*block\s?([a-z0-9\_]*?)\s?\%\}(.*?)(?>(?:{\%\s*block\s?([a-z0-9\_]*?)\s?\%\}|(?R))*\{\%\s?endblock\s?\1?\s?\%\}\is

编辑:我的问题被标记为重复,但我不认为它与该问题有关,我的情况不同,其中块可能无限期地在块内。

1 个答案:

答案 0 :(得分:0)

使用正则表达式:'/(\ *){%\sblock.*\s%}((?:.*|\n)*?)\1{%\sendblock.*\s%}/'

为了使其工作,它确实假设块格式正确,但如果它们格式正确,这在大多数情况下都有效(它使用每个块之前的空格来确定标签是否匹配)。 / p>

尝试这个尺寸:

<?php

function getBlockText($blockText)
{
    $regex = '/(\ *){%\sblock.*\s%}((?:.*|\n)*?)\1{%\sendblock.*\s%}/';
    $recursedMatches= [];
    preg_match_all($regex, $blockText, $matches);
    for ($i = 0; $i < count($matches[2]); $i++) {
        if(preg_match($regex, $matches[2][$i])){
            array_push($recursedMatches, getBlockText($matches[2][$i]));
        } else {
            array_push($recursedMatches, $matches[2][$i]);
        }
    }

    return $recursedMatches;
}


$str = '{% block works %}
    This works
{% endblock %}

{% block main_block %}
    {% block sub_block %}
        Does not work
    {% endblock %} #ends here
    This is not covered
    {% block sub_block %}
        Does not work
    {% endblock %}
{% endblock %}';

print_r(getBlockText($str));

输出:

Array
(
    [0] => 
    This works

    [1] => Array
        (
            [0] => 
        Does not work

            [1] => 
        Does not work

        )

)