0

我有一个类似于 Twig 的模板结构。我用正则表达式划分这个目前成功的。

{% for array as item %}
    {% item.party %}
    {% item %}
{% else %}
    // If empty...
{% endfor %}

{% if !var %}
   // Full
{% else %}
   // Empty
{% endif %}

// Is var full, replace block whit var
{% block var %}
   Some Code
{% endblock %}

正则表达式 preg_match_all('/(?:{% (for|if|block) )(.*?)(?: %})(.*?)({% else %}(.*?))?(?:{% end\1 %})/is', $content, $data);

现在我想那个也可以嵌套。唯一的问题是循环总是走错端。外循环采用内端,因为它是第一个。

{% for array as item %} // From here on
   {% item.title %}
   {% for item.sub as sub %}
      {% sub.title %}
   {% endfor %} // To here
{% endfor %}

你知道我如何让正则表达式选择正确的结尾吗?在第一层的内容上,我还可以重新应用整个功能。但它必须是正则表达式才能使用正确的结尾。

4

1 回答 1

1

The following seems to meet your requirements.

It uses (?R) to allow recursive matching of the whole expression within a block.
See Recursive patterns and PCRE.

preg_match_all(
    '/(?:{% (for|if|block) )(.*?)(?: %})(?:(?R)|(.*?)({% else %}(.*?))?)*(?:{% end\1 %})/is',
     $content, $data
);

The only changes I made to your expression were additions to surround the block's inner content sub-pattern in a non-capturing group, and to add the (R) alternative to it:

start(?:(?R)|inner)end

The (?R) attempts to match the whole regular expression, thereby matching any other blocks within the outer block.

You could also surround the (?R) with parentheses, i.e. ((?R)), so these inner blocks will be available in the third capture group.

于 2013-03-03T22:57:49.863 回答