我为此尝试了不同的想法但尚未成功。因此这篇文章。
一些背景:我正在尝试破译可能包含来自单独文件的变量的Makefile。我已经设法读取Makefile中的所有变量,并且还成功地将其包含到python词典中。但现在我发现每个值基本上都引用了作为字典一部分的其他变量。我想要做的是展开字典中的所有值,使其具有独立于其他键/值对的文本。这肯定涉及递归(恕我直言),但我非常有兴趣听取任何其他建议。
请注意,并非所有变量都可能具有与之关联的值。在这种情况下,请使用NULL字符串替换密钥。
现在有些代码可以演示上面说的内容:
让键,值对的列表为
* A = -L $ {F} $ {B} $ {D},
* B = -L / myhome,
* F = / usr / lib
我想写一个python脚本(可能带有正则表达式)以递归方式将匹配'$ {XXX}'的值替换为相应的键,直到没有更多可用的值与指定的模式匹配(即,所有内容都展开) 。由于D没有与之关联的值,我希望A的值最终为(例如)
* A = -L / usr / lib -L / myhome
提前致谢。任何帮助将不胜感激。
答案 0 :(得分:4)
利用re.subn
,它返回替换次数(让你知道何时停止)并接受repl
参数的函数(从vars字典中选择值):
import re
vs = {
'A' : '-L${F} ${B} ${D}',
'B' : '-L/myhome',
'F' : '/usr/lib',
}
while 1:
treps = 0
for k in vs:
ns, nreps = re.subn(r'''\${(\w+)}''', lambda match: vs.get(match.group(1), ''), vs[k])
if nreps: vs[k] = ns
treps += nreps
if not treps: break
print(vs)
# {'A': '-L/usr/lib -L/myhome ', 'B': '-L/myhome', 'F': '/usr/lib'}
如果A = $ {A},或者A = $ {B}且B = $ {A},请注意上述程序永远不会结束。你没有具体说明在这种情况下会发生什么。
答案 1 :(得分:2)
使用辅助函数进行递归扩展,您可以使用re.sub
替换每个值中的所有非重叠匹配:
import re
RE_VAL = re.compile(r'\${(.*?)}')
def expand (val, src):
return RE_VAL.sub(lambda m: expand(src.get(m.group(1), ''), src), val)
def main ():
vals = {
'A': '-L${F} ${B} ${D}',
'B': '-L/myhome',
'D': '${E}',
'E': '${G}',
'F': '/usr/lib',
'G': '-O',
}
for k,v in vals.iteritems():
vals[k] = expand(v, vals)
print vals
# {'A': '-L/usr/lib -L/myhome -O', 'B': '-L/myhome', 'E': '-O', 'D': '-O', 'G': '-O', 'F': '/usr/lib'}
答案 2 :(得分:0)
这样的事情:
def unroll(stuff):
# Code to unroll.
# if something had been replaced:
replaced = True
# else
replaced = False
return stuff, replaced
def main():
stuff, replaced = unroll(stuff)
while replaced:
stuff, replaced = unroll(stuff)
注意无限的替换循环!