如何用Python正则表达式递归提取代码中所有带括号的标识符(含函数调用、控制语句)
如何用Python正则表达式递归提取代码中所有带括号的标识符(含函数调用、控制语句)
嘿,你想要的效果完全可以通过递归正则实现!Python的re模块支持递归匹配,刚好能解决你这种嵌套括号的场景,咱们一步步来梳理:
先明确你的核心需求
你需要提取所有紧跟在(前面的合法标识符——不管括号里是空的、有内容,还是嵌套了其他括号,这些标识符包括函数名(比如func1)、控制语句关键字(比如if)。
分析你之前尝试的问题
你之前写的正则要么匹配范围太宽泛(比如.*?(?=\s?\()会抓到很多无关的字符串片段),要么方向不对(第二个正则是在匹配括号内部的内容,而非括号前的标识符),所以没得到预期结果。
解决方案:递归正则表达式
我们可以写一个能识别嵌套括号的正则,同时精准捕获括号前的标识符:
import re string = "int a = {0}; func1(arg1, arg11); if(var1 == data1 && func2(arg2)) { var2 = func3(arg3, func4(arg4)) func5(var5) } else { (void)func6(arg6) }" # 递归正则,专门匹配带括号的标识符 pattern = r'\b([a-zA-Z_]\w*)\s*\((?:[^()]|(?R))*\)' result = re.findall(pattern, string) print(result)
运行这段代码,输出正好是你想要的:['func1', 'if', 'func2', 'func3', 'func4', 'func5', 'func6']
正则逻辑拆解
咱们来拆一下这个正则为什么能 work:
\b:单词边界,确保我们匹配的是完整的标识符(不会抓到其他字符串的片段)([a-zA-Z_]\w*):捕获组,匹配Python合法标识符(以字母/下划线开头,后面跟字母、数字、下划线)\s*:匹配括号前可能存在的空格(比如if (var1)里的空格)\(:匹配左括号(?:[^()]|(?R))*:非捕获组,处理括号内部的内容:要么是非括号字符,要么递归匹配整个正则模式(完美解决嵌套括号的问题,比如func3(arg3, func4(arg4))里的func4也能被识别)\):匹配对应的右括号
关于递归正则的说明
你问的“Is there any way to recursively call regex?”——当然可以!Python的re模块支持两种递归方式:
(?R):直接引用整个正则模式,就像我们上面用的那样- 命名分组+
(?P=group_name):如果你的正则有命名分组,可以用这种方式递归引用特定分组
一些注意事项
- 这个正则假设你的代码括号都是成对闭合的,如果有语法错误(比如未闭合的括号),可能会匹配出错
- 它不会区分字符串中的括号(比如
print("hello (world)")里的括号会被误判),如果要处理这种复杂场景,更推荐用Python的ast模块(抽象语法树)来解析代码,比正则更可靠 - 像
(void)这种前面没有标识符的括号结构,不会被捕获,符合你的需求
备注:内容来源于stack exchange,提问作者d_k
相关产品推荐
相关产品推荐

