2013-03-03 81 views
0

我有一個模板結構,它類似於樹枝。我將這個成功與正則表達式分開。閱讀模板與嵌套循環由正則表達式

{% 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 %} 

你知道我是如何得到正則表達式來選擇正確的結尾嗎?在第一級的內容上,我也可以重新應用整個功能。但它必須是使用正確結束的正則表達式。

+3

這可以用'(?R)'和朋友來完成。但你最好用代碼而不是正則表達式解析它。使用regex作爲詞法分析器來標記輸入,然後用PHP解析標記。 – Qtax 2013-03-03 19:42:16

回答

1

以下似乎滿足您的要求。

它使用(?R)來允許塊內整個表達式的遞歸匹配。
請參閱Recursive patternsPCRE

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

我您的表達進行的唯一變化是增加圍繞一非捕獲組中的塊的內部內容子圖案,並以(R)替代添加到它:

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

(?R)嘗試匹配整個正則表達式,從而匹配外部塊內的任何其他塊。

您也可以用圓括號包圍(?R),即((?R)),因此這些內部塊將在第三個捕獲組中可用。