正则表达式匹配Python函数调用

时间:2011-12-28 16:32:52

标签: python regex

我想在Python中创建一个与Python源代码中的一行匹配的正则表达式,并返回一个函数调用列表。

典型的线条如下所示:

something = a.b.method(time.time(), var=1) + q.y(x.m())

,结果应为:

["a.b.method()", "time.time()", "q.y()", "x.m()"]

我有两个问题:

  1. 创建正确的模式
  2. 捕获组重叠
  3. 谢谢你的帮助

5 个答案:

答案 0 :(得分:11)

我不认为正则表达式是最好的方法。请考虑使用ast module,例如:

class ParseCall(ast.NodeVisitor):
    def __init__(self):
        self.ls = []
    def visit_Attribute(self, node):
        ast.NodeVisitor.generic_visit(self, node)
        self.ls.append(node.attr)
    def visit_Name(self, node):
        self.ls.append(node.id)


class FindFuncs(ast.NodeVisitor):
    def visit_Call(self, node):
        p = ParseCall()
        p.visit(node.func)
        print ".".join(p.ls)
        ast.NodeVisitor.generic_visit(self, node)


code = 'something = a.b.method(foo() + xtime.time(), var=1) + q.y(x.m())'
tree = ast.parse(code)
FindFuncs().visit(tree)

结果

a.b.method
foo
xtime.time
q.y
x.m

答案 1 :(得分:4)

$ python3
>>> import re
>>> from itertools import chain
>>> def fun(s, r):
...     t = re.sub(r'\([^()]+\)', '()', s)
...     m = re.findall(r'[\w.]+\(\)', t)
...     t = re.sub(r'[\w.]+\(\)', '', t)
...     if m==r:
...         return
...     for i in chain(m, fun(t, m)):
...         yield i
...
>>> list(fun('something = a.b.method(time.time(), var=1) + q.y(x.m())', []))
['time.time()', 'x.m()', 'a.b.method()', 'q.y()']

答案 2 :(得分:2)

/([.a-zA-Z]+)\(/g

应与方法名称匹配;因为你有一些嵌套,你必须添加parens。

答案 3 :(得分:1)

我真的不懂Python,但我可以想象,正确使用这项工作会带来一些复杂性,例如:

  • 字符串
  • 评论
  • 返回对象的表达式

但是对于你的例子,这样的表达式有效:

(?:\w+\.)+\w+\(

答案 4 :(得分:0)


我有一个例子证明这在Python3中是可行的

    import re


    def parse_func_with_params(inp):
        func_params_limiter = ","
        func_current_param = func_params_adder = "\s*([a-z-A-Z]+)\s*"

        try:
            func_name = "([a-z-A-Z]+)\s*"
            p = re.compile(func_name + "\(" + func_current_param + "\)")
            print(p.match(inp).groups())
        except:
            while 1:
                func_current_param += func_params_limiter + func_params_adder
                try:
                    func_name = "([a-z-A-Z]+)\s*"
                    p = re.compile(func_name + "\(" + func_current_param + "\)")
                    print(p.match(inp).groups())
                    break
                except:
                    pass

命令行输入:animalFunc(lion,tiger,giraffe,singe)
输出:('animalFunc','lion','tiger','giraffe','singe')

如您所见,函数名称始终是列表中的第一个,其余的是传递的参数名称