可以用单个正则表达式解析函数参数吗?
问题
有一个程序文件,在某个地方包含了以下代码片段。
...
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的回答,我找到了相关的问题:
5 个回答
2
为什么要用正则表达式(regex)?
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$']
2
Pyparsing 是一个很方便的工具,特别是在你不知道什么时候会遇到多余的空格、注释或者其他东西的时候。就像正则表达式中的命名组,这个例子定义了一个叫 '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']
3
针对你的问题“能不能用一个正则表达式来完成?”:可以,但在Python里不行。
如果你想要匹配并单独捕获不确定数量的匹配项,就像你举的例子那样,使用一个正则表达式的话,你需要一种支持捕获的正则引擎(而不是捕获组)。目前只有.NET和Perl 6支持这种功能。
所以在Python中,你要么需要分两步来做(先用find
找到整个food(...)
函数调用,然后再用第二个正则表达式通过findall
找到单独的匹配项,就像Dingo建议的那样)。
或者你可以使用像Paul McGuire的pyparsing
这样的解析器。