如何使用正则表达式递归匹配未知层级的嵌套函数?
问题根源
你之前编写的递归正则无法提取全层级函数调用,核心原因有两点:
- 递归段额外包裹了一层无用捕获括号,易造成捕获组序号错乱
- 常规匹配逻辑下,正则引擎完成一次匹配后会直接跳转至本次匹配内容的末尾继续扫描:第一次匹配会直接命中最外层的
DoA(DoB(DoC())),之后扫描指针直接跳到最后一个右括号外侧,后续仅剩余分号,自然无法捕获内层嵌套的调用。
可用正则方案
以下正则基于PCRE递归语法实现,兼容PHP、Java、JavaScript ES2018+、Python regex模块等绝大多数支持递归正则的环境:
(?=([a-zA-Z]+\((?:[^()]|(?1))*\)))
如果需要匹配包含下划线、数字的标准标识符格式函数名,可将函数名匹配段替换为[a-zA-Z_][a-zA-Z0-9_]*,对应正则为:
(?=([a-zA-Z_][a-zA-Z0-9_]*\((?:[^()]|(?1))*\)))
实现逻辑说明
- 外层用
(?=...)正向零宽先行断言包裹完整匹配规则:断言不会消耗匹配到的字符,每次在当前位置完成匹配判断后,引擎仅会向后移动1个字符继续扫描,不会跳过嵌套在括号内的内容 - 第一个捕获组
([a-zA-Z]+\((?:[^()]|(?1))*\))负责匹配单个完整函数调用:[a-zA-Z]+匹配函数名\(匹配函数起始左括号(?:[^()]|(?1))*匹配括号内的所有内容:既可以是非括号的普通字符,也可以通过(?1)递归复用第一个捕获组的规则,匹配嵌套的内层函数调用\)匹配函数结束右括号
- 开启全局匹配模式
g后,按顺序提取每次匹配结果的第一个捕获组内容,即可得到从外到内所有层级的函数调用,支持任意未知深度的嵌套场景。
效果验证
针对测试文本DoA(DoB(DoC()));,最终提取结果完全符合要求:
DoA(DoB(DoC())) DoB(DoC()) DoC()
内容的提问来源于stack exchange,提问作者Chebz
相关产品推荐
相关产品推荐

