问题
程序文件在文件中的某个位置包含以下代码段。
...
food($apples$ , $oranges$ , $pears$ , $tomato$){
...
}
...
此函数可能包含任意数量的参数,但它们必须是以逗号分隔的字符串。所有参数字符串都是小写字。
我希望能够使用正则表达式解析每个参数。例如,python中的结果列表如下:
["apples", "oranges", "pears", "tomato"]
尝试解决方案
使用python RE模块,我可以通过将问题分成两部分来实现这一目标。
在代码中找到函数并提取参数列表。
plist = re.search(r'food\((.*)\)', programString).group(1)
使用其他正则表达式拆分列表。
params = re.findall(r'[a-z]+', plist)
问题
无论如何,我可以用一个正则表达而不是两个来实现这个目的吗?
修改
感谢Tim Pietzcker的回答,我找到了一些相关的问题:
答案 0 :(得分:2)
当您不知道什么时候会遇到额外的空白,评论等等时,Pyparsing对于这种事情很方便。与RE中的命名组一样,此示例定义结果名称'parameters',用于检索所需数据:
>>> code = """\
... ...
...
... food($apples$ , $oranges$ , $pears$ , $tomato$){
... ...
... }
... ...
... food($peanuts$, $popcorn$ ,$candybars$ ,$icecream$){
... ...
... }
... """
>>> from pyparsing import *
>>> LPAR,RPAR,LBRACE,RBRACE,DOLLAR = map(Suppress,"(){}$")
>>> param = DOLLAR + Word(alphas) + DOLLAR
>>> funcCall = "food" + LPAR + delimitedList(param)("parameters") + RPAR + LBRACE
>>> for fn in funcCall.searchString(code):
... print fn.parameters
...
['apples', 'oranges', 'pears', 'tomato']
['peanuts', 'popcorn', 'candybars', 'icecream']
如果我将第二个功能更改为:
... food($peanuts$, $popcorn$ ,/*$candybars$ ,*/$icecream$){
然后添加以下行:
>>> funcCall.ignore(cStyleComment)
然后我得到:
>>> for fn in funcCall.searchString(code):
... print fn.parameters
...
['apples', 'oranges', 'pears', 'tomato']
['peanuts', 'popcorn', 'icecream']
答案 1 :(得分:2)
回答你的问题“它可以在一个正则表达式中完成吗?”:是的,但不是用Python。
如果你想匹配和捕获(单独)一个未知数量的匹配,就像在你的例子中一样,只使用一个正则表达式,那么你需要a regex engine that supports captures (as opposed to capturing groups)。目前只有.NET和Perl 6才能这样做。
所以在Python中,你需要分两步完成(find
整个food(...)
函数调用,然后findall
个人匹配第二个正则表达式,如Dingo所建议的那样)
或者像Paul McGuire的pyparsing
一样使用解析器。
答案 2 :(得分:1)
为何选择正则表达式?
for line in open("file"):
line=line.rstrip()
if line.lstrip().startswith("food") :
for item in line.split(")"):
if "food" in item:
print item.split("(")[-1].split(",")
输出
$ ./python.py
['$apples$ ', ' $oranges$ ', ' $pears$ ', ' $tomato$']
答案 3 :(得分:0)
params = re.findall(r'\$([a-z]+)\$', programString)
答案 4 :(得分:0)
像这样的正则表达式应该有效
food\((\$(?<parm>\w+)\$\s*,?\s*)+\).*
它将所有匹配的参数名称放在'parm'组
中