我有code.py
:
def funA():
print('A')
funA()
def funB():
print('B')
def funC():
print('C')
funB()
funC()
我想找到所有函数自称:
funA
funC
如何撰写regex
?
约束:
funname(arg1, arg2, ...)
lambda
,exec
)答案 0 :(得分:2)
这很难,因为该函数可以用混淆的方式调用自己。例如,这算了吗?
def funA():
print 'A'
foo = funA
foo()
funA()
这个怎么样?
def funA():
funB()
def funB():
funA()
funA()
甚至是这个?
def funA():
exec('Anuf'[::-1] + '()')
funA()
我认为你不能用正则表达式做到这一点。
即使考虑到您的新编辑,如果不是不可能的话,仍然会非常困难。例如,考虑这个功能。
def funA():
if 1 + 1 == 2:
return
funA()
我建议您遵循Ignacio Vazquez-Abrams的建议并查看ast。
答案 1 :(得分:1)
简单地说,你将无法用正则表达式做到这一点。您至少需要解析函数定义,保留当前正在解析的函数的某种状态,并在当前函数的范围内搜索当前函数名的调用。
答案 2 :(得分:1)
是的我确实认为正则表达式不可能匹配wim指出的自我调用被混淆的情况。但是,这里有一个正则表达式,可以为简单的自我调用做一个半体面的工作(格式为funcname(...)
)。此正则表达式正确匹配原始问题中拼写的所有测试用例:
reobj = re.compile(r"""
# Match (unreliably) Python function with self reference.
^ # Anchor to start of line.
([ \t]*) # $1: Indentation of DEF statement.
def[ \t]+ # Function definition.
([^\s(]+) # $2: Name of function to find.
.*\r?\n # Remainder of function def line.
(?: # Zero or more lines w/o funcname.
(?: # Function block lines alternatives.
\1[ \t]+ # Func block lines have extra indentation.
(?:(?!\b\2\s*\().)* # Optional non-funcname stuff on line
| [ \t]*\#.* # Allow comment lines to defy indent rules.
)? # Allow blank lines in function block.
\r?\n # End of line not containing funcname.
)* # Zero or more lines w/o funcname
\1[ \t]+ # Now match the line having funcname.
(?:(?!\b\2\s*\().)* # Optional non-funcname stuff on line
\b\2\s*\( # Match the function self reference.
""", re.MULTILINE | re.VERBOSE)
它与函数定义行匹配,并在组'def'
中的$1
和组$2
中的函数名称之前捕获空白缩进。然后它匹配功能块中不包含函数名的行,每个函数名都有比函数定义更多的前导空格。它跳过空行和仅包含注释的行。一旦它在功能块中找到一行,其后面有一个左括号,表示对它自己的调用,它就会声明一个匹配。否则,它声明不匹配,然后继续寻找下一个可能的匹配。
请注意,此解决方案不可靠,如果函数名称出现在字符串内或符合行上其他代码的注释内,则会导致误报。它也不处理多行原始字符串的函数。但是,它会正确地捕获一些!
答案 3 :(得分:0)
我将描述我认为你想要的模式:一行以def开头,后跟空格,后跟一个名称(你在括号中捕获),后跟一组(可能是空的)行开始使用空格,后跟一行以空格开头并包含您的函数名称后跟一个打开的paren(以便捕获实际的调用,而不仅仅是引用)。
答案 4 :(得分:0)
可能你可以使用gawk,下面是我的示例代码,你可能需要修改它:
#! /usr/bin/gawk -f
{
currentLine = $0
if (currentLine ~ /def/){
inFunction = "true"
nameIndex = index($2,"(")
functionName = substr($2,1,nameIndex - 1)
#print functionName
next
}
if (inFunction == "true" && currentLine ~ functionName){
inFunction = false
print "recursive function is: " functionName
}
}
只需运行程序就可以得到你想要的东西。