PHP v8 preg_match_all匹配嵌套双花括号令牌及文本的正则需求
匹配嵌套双花括号令牌的PHP正则方案
需求说明
使用PHP 8的preg_match_all函数,实现两类内容的精准匹配:
- 普通字面文本(允许包含单花括号
{/}) - 最外层双花括号令牌
{{...}},支持令牌嵌套,仅捕获最外层结构;令牌内部允许出现单花括号,仅{{和}}作为令牌的起始/结束分隔符。
示例输入
This {is {{Par}m1}} plus {{Par{m3a{{Parm3b}}}} a}nd {{Parm4a||{{Par}m4b||{{Parm4c||{{Parm4d||Parm}}}}}}}}.
预期匹配结果
Match 1: This {is Match 2: {{Par}m1}} Match 3: plus Match 4: {{Par{m3a{{Parm3b}}}} Match 5: a}nd Match 6: {{Parm4a||{{Par}m4b||{{Parm4c||{{Parm4d||Parm}}}}}}}} Match 7: .
现有方案问题
- 原正则
(?:(?!(\{\{)).)+|((\{\{)((?>[^\{\}]+|(?2))*)(\}\})):无法兼容含单花括号的场景,[^\{\}]+会排除所有单花括号,导致令牌内的单花括号被截断。 - 递归正则
\{\{(?R)*\}\|[^\{\}]+:逻辑错误,未正确处理单花括号,匹配规则混乱,无法完成预期解析。
解决方案正则
$pattern = '~(?:(?!{{).)+|({{(?:[^{}]|{(?![{])|}(?![}])|(?R))*}})~s'; preg_match_all($pattern, $input, $matches, PREG_PATTERN_ORDER); $results = $matches[0];
正则解析
- 分隔符:使用
~作为正则分隔符,避免与花括号冲突 s修饰符:让.匹配换行符,提升通用性- 第一分支
(?:(?!{{).)+:匹配普通文本(?!{{):负前瞻断言,确保当前位置后不是令牌起始符{{.:匹配任意字符(含单花括号),重复匹配直到遇到{{或字符串结束
- 第二分支
({{(?:[^{}]|{(?![{])|}(?![}])|(?R))*}}):匹配最外层令牌{{:匹配令牌起始标记- 内部非捕获组
(?:...)定义令牌允许的内容:[^{}]:匹配非花括号的任意字符{(?![{]):匹配单个{(排除{{)}(?![}]):匹配单个}(排除}})(?R):递归调用整个正则模式,实现嵌套令牌的匹配
*:重复匹配内部内容,直到遇到对应的}}}}:匹配令牌结束标记
验证结果
将示例输入代入上述代码,$results数组将完全符合预期匹配结果,可正确区分普通文本与最外层嵌套令牌,完美兼容单花括号场景。
内容的提问来源于stack exchange,提问作者Russ
相关产品推荐
相关产品推荐

