以下是我想提取标签{{if}}
和{{'if}}
之间包含的字符串,我指的是第一个和最后一个(内部字符串将由引擎重新检查):
- "在{{if^^p1^p2}}IN1之前;{if^ ^p1}}
- "在{{if^^p1}}IN1之前;{if^ ^p1}
- "在{{if^^p1}}IN1之前;{if^ ^p1}
正则表达式为:'{'{(if)'}'}(((?!'{'{'/?'1'}'})['s'S])*('{'{'1'}'}(?2)*'{'{'/'1'}'})*((?!'{'{'/?'1'}'})['s'S])*)'{'{'/'1'}'}
第3版:我取消了支持TAG的义务,但没有终止TAG。我为未来的用户重新格式化了这个问题,为了理解下面的一些评论,请参阅文章的第一个版本
更重要的是,我让它同时适用于所有三个,给我三个匹配,这在regex101网站上不起作用。比赛中必须支持换行符。不过,我可以接受只有最后两个组合才能给出两个匹配,因为我可以将单独的if
的标签更改为iif
。
我的另一个解决方案是不使用正则表达式,但如果可能的话,我愿意这样做。
您可以使用
~{{ # Opening tag start
('w+) # (Group 1) Tag name
'^ # Aux delimiter
([^^'{'}]?) # (Group 2) Specific delimiter
'^ # Aux delimiter
([^'{'}]+) # (Group 3) Parameters
}} # Opening tag end
( # (Group 4)
(?>
(?R) # Repeat the whole pattern
| # or match all that is not the opening/closing tag
[^{]*(?:'{(?!{/?'1[^'{'}]*}})[^{]*)*
)* # Zero or more times
)
{{/'1}} # Closing tag
~ix
查看regex演示
一般来说,该表达式是基于递归和经过调和的贪婪令牌的。[^{]*(?:'{(?!{/?'1[^'{'}]*}})[^{]*)*
部分是展开的(?s:(?!{{/?'1}}).)*
模式,其匹配不是{{TAG}}
或{{/TAG}}
字符序列的起点的任何字符(.
)。
此模式不需要DOTALL修饰符,因为该模式中没有.
。
下面是一个PHP演示:
$re = '~{{('w+)'^([^^'{'}]?)'^([^'{'}]+)}}((?>(?R)|[^{]*(?:'{(?!{/?'1[^'{'}]*}})[^{]*)*)*){{/'1}}~i';
$str = "before {{if^^p1^p2}} IN1; {{if^ ^p1}} {{iif}} IN3 {{/if}} IN1-1 {{/if}} after'nbefore {{if^ ^p1}} IN1; {{if^ ^p1}} {{if^ ^p1}} IN3 {{/if}} {{/if}} IN1-1 {{/if}} after'nbefore {{if^ ^p1}} IN1; {{if^ ^p1}} {{if^ ^p1}} IN3 {{/if}} {{/if}} IN1-1 {{if^ ^p1}} IN4 {{/if}} {{/if}} after";
preg_match_all($re, $str, $matches);
print_r($matches);