使用PHP preg_match_all提取所有合法的模板标签组
解决嵌套Liquid标签提取的正则方案
要提取包含嵌套结构的完整{% if/case %}标签组,PHP的PCRE支持递归正则,可以用以下正则表达式实现:
~{%\s*(if|case)\b[^}]*%}(?:(?!{%\s*end\1\b[^}]*%}).|(?R))*{%\s*end\1\b[^}]*%}~s
正则规则解析
~:作为正则分隔符,避免与标签内的/冲突{%\s*(if|case)\b[^}]*%}:匹配起始标签,捕获if或case到分组1,\b确保匹配完整的标签关键字,[^}]*匹配标签内的任意内容(直到%})(?:(?!{%\s*end\1\b[^}]*%}).|(?R))*:非捕获组,处理中间内容:(?!{%\s*end\1\b[^}]*%}):负前瞻判断,当前位置不是对应结束标签的开头.:匹配任意字符(含换行,因为s修饰符)|(?R):如果遇到新的起始标签,递归匹配整个正则模式,处理嵌套结构
{%\s*end\1\b[^}]*%}:匹配对应结束标签,\1引用分组1的标签类型,确保if对应endif、case对应endcases修饰符:让.匹配换行符,支持跨行内容
PHP代码示例
$str = '{% if test %} random text here {% case item %}{% when "hello" %}hi{% else %}goodbye{% endcase %} {% if hello %}text here{% else %}new text{% endif %} random text here {% endif %} {% case item %}{% when "hello" %}hi{% else %}goodbye{% endcase %}'; preg_match_all('~{%\s*(if|case)\b[^}]*%}(?:(?!{%\s*end\1\b[^}]*%}).|(?R))*{%\s*end\1\b[^}]*%}~s', $str, $matches); print_r($matches[0]);
执行后会输出:
Array ( [0] => {% if test %} random text here {% case item %}{% when "hello" %}hi{% else %}goodbye{% endcase %} {% if hello %}text here{% else %}new text{% endif %} random text here {% endif %} [1] => {% case item %}{% when "hello" %}hi{% else %}goodbye{% endcase %} )
内容的提问来源于stack exchange,提问作者Tikboy
相关产品推荐
相关产品推荐

