Python正则替换 - 在替换中使用匹配作为字典键

11 投票
1 回答
9805 浏览
提问于 2025-04-17 23:12

我正在把一个程序从Perl语言转到Python(3.3)。我对Python还比较陌生。在Perl中,我可以做一些很巧妙的正则表达式替换,比如:

$string =~ s/<(\w+)>/$params->{$1}/g;

这个代码会在中查找内容,对于每一组被<>包围的单词字符,它会用$params这个哈希表中的值进行替换,使用正则表达式匹配到的内容作为哈希表的键。

那么在Python中,有什么好的(符合Python风格的)方法可以简洁地实现这个功能呢?我想出了类似这样的代码:

string = re.sub(r'<(\w+)>', (what here?), string)

如果我能传递一个函数,把正则表达式匹配的结果映射到一个字典中,那会很好。这样做可以吗?

谢谢你的帮助。

1 个回答

17

你可以给 re.sub 传一个可调用的对象,这样它就知道该如何处理匹配到的内容。

s = re.sub(r'<(\w+)>', lambda m: replacement_dict.get(m.group()), s)

使用 dict.get 可以让你提供一个“备用方案”,也就是说,如果你要替换的单词不在替换字典里,就会使用这个备用方案。

lambda m: replacement_dict.get(m.group(), m.group()) 
# fallback to just leaving the word there if we don't have a replacement

我想提一下,当使用 re.sub(还有 re.split 等相关函数)时,如果你想指定一些在你想替换的内容周围的东西,通常使用“前后查找”表达式会更简洁,这样就不会把匹配内容周围的东西也替换掉。因此在这种情况下,我会这样写你的正则表达式:

r'(?<=<)(\w+)(?=>)'

否则你就得在你的 lambda 里处理一下括号的切割和再拼接。为了让你更清楚我在说什么,给你一个例子:

s = "<sometag>this is stuff<othertag>this is other stuff<closetag>"

d = {'othertag': 'blah'}

#this doesn't work because `group` returns the whole match, including non-groups
re.sub(r'<(\w+)>', lambda m: d.get(m.group(), m.group()), s)
Out[23]: '<sometag>this is stuff<othertag>this is other stuff<closetag>'

#this output isn't exactly ideal...
re.sub(r'<(\w+)>', lambda m: d.get(m.group(1), m.group(1)), s)
Out[24]: 'sometagthis is stuffblahthis is other stuffclosetag'

#this works, but is ugly and hard to maintain
re.sub(r'<(\w+)>', lambda m: '<{}>'.format(d.get(m.group(1), m.group(1))), s)
Out[26]: '<sometag>this is stuff<blah>this is other stuff<closetag>'

#lookbehind/lookahead makes this nicer.
re.sub(r'(?<=<)(\w+)(?=>)', lambda m: d.get(m.group(), m.group()), s)
Out[27]: '<sometag>this is stuff<blah>this is other stuff<closetag>'

撰写回答