例如,我有这样一个字符串:
{% a %}
{% b %}
{% end %}
{% end %}
我想获取{% a %}
和{% end %}
之间的内容,即{% b %} {% end % }
.
我曾经使用 {%\S+ %}(.*){% end %} 来做到这一点。但是当我在其中添加 c 时:
{% a %}
{% b %}
{% end %}
{% end %}
{% c %}
{% end %}
它不起作用...我怎么能用正则表达式做到这一点?
最佳答案
鉴于此测试数据:
$text = '
{% a %}
{% b %}
{% a %}
{% end %}
{% end %}
{% b %}
{% end %}
{% end %}
{% c %}
{% end %}
';
这个经过测试的脚本可以解决问题:
<?php
$re = '/
# Match nested {% a %}{% b %}...{% end %}{% end %} structures.
\{%[ ]\w[ ]%\} # Opening delimiter.
(?: # Group for contents alternatives.
(?R) # Either a nested recursive component,
| # or non-recursive component stuff.
[^{]*+ # {normal*} Zero or more non-{
(?: # Begin: "unrolling-the-loop"
\{ # {special} Allow a { as long
(?! # as it is not the start of
%[ ]\w[ ]%\} # a new nested component, or
| %[ ]end[ ]%\} # the end of this component.
) # Ok to match { followed by
[^{]*+ # more {normal*}. (See: MRE3!)
)*+ # End {(special normal*)*} construct.
)*+ # Zero or more contents alternatives
\{%[ ]end[ ]%\} # Closing delimiter.
/ix';
$count = preg_match_all($re, $text, $m);
if ($count) {
printf("%d Matches:\n", $count);
for ($i = 0; $i < $count; ++$i) {
printf("\nMatch %d:\n%s\n", $i + 1, $m[0][$i]);
}
}
?>
这是输出:
2 Matches:
Match 1:
{% a %}
{% b %}
{% a %}
{% end %}
{% end %}
{% b %}
{% end %}
{% end %}
Match 2:
{% c %}
{% end %}
编辑:如果您需要匹配具有多个字符字符的开始标记,请将出现的两次 \w
标记替换为 (?! end)\w++
,(在 tchrist 的出色回答中正确实现)。
关于php - 如何将一些嵌套结构与正则表达式匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5583833/