我想在Python中創建一個正則表達式,它將匹配Python源代碼中的一行並返回函數調用列表。與Python函數調用匹配的正則表達式
典型的線路是這樣的:
something = a.b.method(time.time(), var=1) + q.y(x.m())
,其結果應該是:
["a.b.method()", "time.time()", "q.y()", "x.m()"]
我這裏有兩個問題:
- 創建正確的模式
- 捕獲組重疊
謝謝大家幫忙
我想在Python中創建一個正則表達式,它將匹配Python源代碼中的一行並返回函數調用列表。與Python函數調用匹配的正則表達式
典型的線路是這樣的:
something = a.b.method(time.time(), var=1) + q.y(x.m())
,其結果應該是:
["a.b.method()", "time.time()", "q.y()", "x.m()"]
我這裏有兩個問題:
謝謝大家幫忙
我不認爲正則表達式是最好的方法。考慮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
「ast」模塊上的+1教程!很高興知道它提供的東西比'literal_eval'更有用:) :) – 2011-12-28 19:41:33
事實上,除非我錯了,否則基於正則表達式的方法註定要失敗。 Python語言基於上下文無關語法,並且(除非我錯了),CFG比正則表達式更具表現力(謝謝[Chomsky Hierarchy](http://en.wikipedia.org/wiki/) Chomsky_hierarchy) – 2012-09-10 17:22:59
@AdamParkin:[這個問題]的一些答案(http://stackoverflow.com/questions/11306641/what-kind-of-formal-languages-can-modern-regex-engines-parse)可能是有趣的你 – georg 2012-09-10 18:00:22
/([.a-zA-Z]+)\(/g
應該匹配方法名;因爲你有一些嵌套後你必須添加parens。
'foo(「bar(a,b)」)'會爲該正則表達式錯誤地返回'bar'。 – 2011-12-28 16:42:37
@DouglasLeeder公平點。 – Mathletics 2011-12-28 16:49:17
@DouglasLeeder它看起來不錯,但[this](http://pastebin.com/7dKpRh5B)Python代碼不能打印預期的內容。 – xralf 2011-12-28 17:35:51
我真的不知道Python,但我可以想像,使這項工作正常涉及一些併發症,如:
但是對於您的示例,像這樣的表達式有效:
(?:\w+\.)+\w+\(
$ 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()']
我爲你證明這一點的例子是在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
命令線路輸入put:animalFunc
輸出:('animalFunc','lion','tiger','giraffe','singe')
正如你所看到的,函數名永遠是第一個在列表中,其餘的是通過的參數名稱
那麼解析字符串和註釋怎麼樣? – Qtax 2011-12-28 16:35:51
python不是一種常規的語言,所以你不能用正則表達式。 – 2011-12-28 16:43:05
@DouglasLeeder,正則表達式不正規。除非我們在這裏討論形式語言理論。 ;-) – Qtax 2011-12-28 16:46:13