鑑於這種測試數據:
$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 %}
Ë dit:如果您需要匹配具有多個單詞char的開始標記,請將\w
標記中的兩個出現替換爲(?!end)\w++
(如在tchrist的出色答案中正確實施)。
它是任意深度的嵌套結構嗎?如果是這樣,那不是一種常規語言。 – eldarerathis 2011-04-07 15:46:17
請不要嘗試。 http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454 – casablanca 2011-04-07 15:46:44
你可能會有一個更簡單的時間匹配個別元素與正則表達式和使用一個堆棧,以匹配打開/關閉塊。 – GWW 2011-04-07 15:47:22