我有以下字符串:
{% if a == 3 %}
Yes
{% else %}
{% if b == 2 %}
Maybe
{% else %}
{% if c == 1 %}
Hm... Not
{% else %}
No way!
{% endif %}
{% endif %}
{% endif %}
{% if d == 0 %}
Ok
{% endif %}
如果我使用这个正则表达式
/\{%\s*if\s*(.*?)\s*%\}(.*)(\{%\s*else\s*%\}(.*))?\{%\s*endif\s*%\}/ism
(在PHP上的preg_match_all函数中),我的返回是上面的所有代码。但是当我使用时
/\{%\s*if\s*(.*?)\s*%\}(.*?)(\{%\s*else\s*%\}(.*?))?\{%\s*endif\s*%\}/ism
(刚出贪婪模式),我的回复结束于{% endif %}
{% if c == 1 %}
if(找到第一个endif)。
我希望获得以下回报:
1
{% if a == 3 %}
Yes
{% else %}
{% if b == 2 %}
Maybe
{% else %}
{% if c == 1 %}
Hm... Not
{% else %}
No way!
{% endif %}
{% endif %}
{% endif %}
2
{% if d == 0 %}
Ok
{% endif %}
我的正则表达式如何归档此回报?
PS。我知道,如果我在ifs上添加一些名称并在endif上使用此名称,则可以使用反向引用轻松解决...但我不想要一个姑息性的答案
提前致谢。
答案 0 :(得分:3)
您可以使用此递归模式:
$pattern = '~{% if [^%]+%}(?>[^{]+|(?R))*(?>{% else %}(?>[^{]+|(?R))*)?{% endif %}~';
模式细节:
~
{% if [^%]+%}
(?> # this atomic group describes the content
# between if/else/endif markups:
[^{]+ # - all that is not an opening curly bracket
| # OR
(?R) # - recursion (repeat the whole pattern)
)* # repeat the group zero or more times
(?>
{% else %} # The "else" part works exactly in the same way,
(?>[^{]+|(?R))*
)? # but is optional
{% endif %}
~
答案 1 :(得分:0)
我扩展了这个例子来解决我自己的问题,特别是在其中有一些随机的{%...%}:regex101 online demo