首页/开发/正则与编码速查/递归子模式与嵌套结构匹配
正则进阶45 条

递归子模式与嵌套结构匹配

递归子模式用 (?R)、(?1) 或 (?&name) 让模式调用自身,用来匹配层数不定的嵌套结构,例如配对括号与嵌套占位符。它是回溯引擎特有语法,PCRE、Perl、Oniguruma 与 Python regex 库可用,Python re、Java、.NET 不支持。

正则与编码速查开发更新于 2026-10-17
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌​‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​​‌‌​‌‌‌​‌​‌​‌‌‌​​‌​​‌‌‌​​‌‌​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​‌​‌​‌‌​​​‌​​‌‌‌​​​​​‌‌​​​​‌​‌‌‌​‌​​​‌‌‌​‌​​​‌‌​​‌​‌​‌‌‌​​‌​​‌‌​‌‌‌​​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

递归子模式是什么

递归子模式让一条模式在匹配过程中回头调用自己(或调用其中某个组),从而处理层数不定的嵌套结构,典型用途是配对括号、嵌套表达式、模板嵌套。它的能力来自回溯式引擎的「子程序调用」机制,因此只在 PCRE、Perl、Oniguruma 以及第三方库里有,标准库里的 Python re、Java、.NET 都不支持。

基本信息

整体递归(?R) 或 (?0) 表示重新调用整条模式
按组递归(?1)、(?2) 按组号调用子模式,(?&name) 按组名调用,后者可读性更好
递归条件PCRE 的 (?(R)…) 用于判断当前是否位于递归调用内
支持引擎PCRE/PHP、Perl、Oniguruma/Ruby、Python regex 库支持;re、Java、.NET 不支持

典型使用场景

  • 配对括号:匹配任意层数的圆括号、方括号内容,层数不固定又必须整体配平
  • 嵌套表达式片段:从配置或代码里整段抽取形如 f(g(x), y) 的调用结构
  • 可嵌套模板语法:处理 {{a{ b }c}} 这类嵌套占位符的完整性校验
  • 去掉注释块:把 /* … */ 中再嵌注释的片段作为整体识别出来
  • 文本结构合法性预筛:在解析器之前用递归模式快速判断形态,避免更重的解析开销

递归模式写法示例

递归模式写法示例
(?<paren>\((?:[^()]++|(?&paren))*\))   # 匹配任意层括号,占有量词抑制重复回溯
\( (?: (?&paren) | [^()] )* \)           # 展开写法:先试递归,再吃普通字符
(?R)                                   # 整条模式递归,把所有规则包成一个整体
\g<0>                                 # Ruby、Oniguruma 里调用整条模式
(?<tpl>\{\{(?:[^{}]++|(?&tpl))*\}\})    # 嵌套占位符,仅适用于内部无其他花括号的文本

引擎支持对照

引擎递归写法支持程度
PCRE / PHP(?R)、(?1)、(?&name)完整支持,含递归条件
Perl(?R)、(?1)、(?&name)完整支持
Ruby / Oniguruma\g<0>、\g<name>支持
Python regex 库(?R)、(?&name)支持
Python re / Java / .NET无不支持,需改用解析器或平衡组
递归模式必须保证每轮至少消耗一个字符,否则会陷入无限递归;写法上通常把「普通字符」分支放在递归分支之后,并用占有量词或原子组减少无意义回溯。
递归深度与回溯总量都有引擎上限(PCRE 里是 match limit 与 depth limit),超深输入会匹配失败甚至触发进程保护,线上使用前应对输入长度做硬限制,并准备降级路径。

易错点

  • 以为标准库都支持:Python re、Java、.NET 没有递归语法,模式会直接编译失败,跨语言项目必须在设计阶段就确认
  • 递归分支没有排他性:既允许递归又允许任意字符,会造成天文数字级的回溯,输入稍长就拖垮进程
  • 拿递归模式当解析器:字符串转义、注释、非法嵌套等真实情况远超模式能力,HTML 与 JSON 必须交给真正的解析器
  • 忽略深度限制:超深嵌套下匹配静默失败,被误判为「输入不合法」,业务侧给出错误结论
  • 递归与反向引用混用导致结果不可预期:建议先用组名把子模式定清楚,再决定是否引用

数据来源与参考

  • PCRE2 官方文档:pcre2pattern(Recursive patterns 章节)
  • Perl 官方文档 perlre:递归子模式与 (?R)
  • Python regex 库文档:递归与子程序调用

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/regex/regex-recursion-subpattern.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌​‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​​‌‌​‌‌‌​‌​‌​‌‌‌​​‌​​‌‌‌​​‌‌​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​‌​‌​‌‌​​​‌​​‌‌‌​​​​​‌‌​​​​‌​‌‌‌​‌​​​‌‌‌​‌​​​‌‌​​‌​‌​‌‌‌​​‌​​‌‌​‌‌‌​​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​