[英]PHP RegEx to match nested patterns (possible recursion)
我正在嘗試匹配可能嵌套的模式。
這是一些示例數據,我想在這些數據中提取{{ loop ... }
元素內的內容:
<ul>
{{ loop #users as #u }}
<li>{{ #u.first_name }} {{ #u.last_name }}</li>
{{ endloop }}
</ul>
我用此RegEx正確得到它:
/{{\s+loop\s+#([a-zA-Z_][a-zA-Z0-9_]*)((?:\.[a-zA-Z0-9_]+)*)\s+as\s+#([a-zA-Z_][a-zA-Z0-9_]*)\s+}}(.*){{\s+endloop\s+}}/sU
說明:
/
{{
開環元素的開始
\\s+loop\\s+
loop關鍵字#([a-zA-Z_][a-zA-Z0-9_]*)
變量名( 例如:#var
)((?:\\.[a-zA-Z0-9_]+)*)
可選變量鍵( 例如:#var.key
)\\s+as\\s+
作為關鍵字#([a-zA-Z_][a-zA-Z0-9_]*)\\s+
別名變量名稱( 例如:#alias
)}}
開環元素結束(.*)
循環內容{{\\s+endloop\\s+}}
閉環元素/sU
使用嵌套循環,我需要獲取第一級循環的內容(因為然后在我的項目中遞歸地解析內容)。 以下是一些示例數據:
1| <ul>
2| {{ loop #users as #u }}
3| <li>
4| {{ #u.first_name }} {{ #u.last_name }}
5| <ul>
6| {{ loop #u.friends as #f }}
7| <li>{{ #f.first_name }} {{ #f.last_name }}</li>
8| {{ endloop }}
9| </ul>
10| </li>
11| {{ endloop }}
12| </ul>
13|
14| {{ loop #foo as #bar }}
15| <a href="#">{{ #bar }}</a>
16| {{ endloop }}
使用此內容,模式將在遇到的第一個{{ endloop }}
處停止(第2-8行)。
如果刪除U
標志(不舒適),則無法使用多個循環,因為即使它們是不同的循環(第2-16行),它也會停止到最后一個{{ endloop }}
。
我有使用/m
標志(多行)的模式的先前版本,但是它也失敗了,因為它只匹配最深層次的循環(第6-8行)。
我進行了很多嘗試(大多數是在regexr.com上完成的 ),但是看不到任何進展。 我搜索了有關“遞歸模式”的解決方案,發現的最佳結果是這個問題,但是經過多次嘗試,我無法使其適應我的項目。
(?R)
RegEx中的遞歸的信息,但是還沒有成功使用它,這對我有幫助嗎? 我不僅在尋找解決方案,而且非常感謝了解如何解決這個問題。 鏈接到當前的RegexR: regexr.com/426fd
這是您當前模式的快速修復:
{{\s+loop\s+#([a-zA-Z_]\w*)((?:\.\w+)*)\s+as\s+#([a-zA-Z_]\w*)\s*}}((?:(?!{{\s+(?:end)?loop\s).|(?R))*){{\s+endloop\s+}}
請注意,您不需要U
修飾符即可使此模式按預期運行,但是您仍然需要s
修飾符.
匹配任何字符。
主要區別在於將.*
替換為(?:(?!{{\\s+(?:end)?loop\\s).|(?R))*
。 它與0個或多個重復匹配:
(?!{{\\s+(?:end)?loop\\s).
-任何沒有開始滿足以下模式的序列的char( .
):
{{
- {{
子字符串 \\s+
-1+空格 (?:end)?
-可選的end
子字符串 loop
loop
子字符串 \\s
空格 |
- 要么 (?R)
-整個正則表達式模式 此外,如果您不使用u
修飾語或(*UCP)
PCRE動詞,則[a-zA-Z0-9_]
等於\\w
,因此可以稍微縮短整個模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.