我可以用 re.sub(或 regexobject.sub)在子组中替换文本吗?
我需要解析一个配置文件,格式大致是这样的(简化版):
<config>
<links>
<link name="Link1" id="1">
<encapsulation>
<mode>ipsec</mode>
</encapsulation>
</link>
<link name="Link2" id="2">
<encapsulation>
<mode>udp</mode>
</encapsulation>
</link>
</links>
我的目标是能够修改特定链接的参数,但我在替换时遇到了麻烦。我有一个正则表达式,可以找到特定链接的参数值,这个值在捕获组1里面:
link_id = r'id="1"'
parameter = 'mode'
link_regex = '<link [\w\W]+ %s>[\w\W]*[\w\W]*<%s>([\w\W]*)</%s>[\w\W]*</link>' \
% (link_id, parameter, parameter)
因此,
print re.search(final_regex, f_read).group(1)
打印出来的是 ipsec
在这个 正则表达式教程 中的例子似乎都假设我们想在替换时使用捕获组的内容,但我需要做的是直接替换掉捕获组本身(比如把 Link1 的模式从 ipsec 改成 udp)。
4 个回答
2
这看起来像是有效的XML格式,所以你不需要用BeautifulSoup,也根本不需要用正则表达式。你只需要用一个好的XML库来加载XML,编辑它,然后打印出来。下面是一个使用ElementTree的方法:
import xml.etree.cElementTree as ET
s = """<config>
<links>
<link name="Link1" id="1">
<encapsulation>
<mode>ipsec</mode>
</encapsulation>
</link>
<link name="Link2" id="2">
<encapsulation>
<mode>udp</mode>
</encapsulation>
</link>
</links>
</config>
"""
configElement = ET.fromstring(s)
for modeElement in configElement.findall("*/*/*/mode"):
modeElement.text = "udp"
print ET.tostring(configElement)
这个方法会把所有的mode元素都改成udp
,输出结果如下:
<config>
<links>
<link id="1" name="Link1">
<encapsulation>
<mode>udp</mode>
</encapsulation>
</link>
<link id="2" name="Link2">
<encapsulation>
<mode>udp</mode>
</encapsulation>
</link>
</links>
</config>
6
我得先告诉你一句:“别用正则表达式来做这个。”
看看用BeautifulSoup来做这件事是多么简单和好用,比如说:
>>> from BeautifulSoup import BeautifulStoneSoup
>>> html = """
... <config>
... <links>
... <link name="Link1" id="1">
... <encapsulation>
... <mode>ipsec</mode>
... </encapsulation>
... </link>
... <link name="Link2" id="2">
... <encapsulation>
... <mode>udp</mode>
... </encapsulation>
... </link>
... </links>
... </config>
... """
>>> soup = BeautifulStoneSoup(html)
>>> soup.find('link', id=1)
<link name="Link1" id="1">
<encapsulation>
<mode>ipsec</mode>
</encapsulation>
</link>
>>> soup.find('link', id=1).mode.contents[0].replaceWith('whatever')
>>> soup.find('link', id=1)
<link name="Link1" id="1">
<encapsulation>
<mode>whatever</mode>
</encapsulation>
</link>
看你的正则表达式,我不太确定这是不是你想要的效果,但无论你想做什么,使用像BeautifulSoup这样的库要比拼凑正则表达式好得多。我强烈推荐如果可以的话就走这条路。
0
我不太确定这样做是否合适,但最快的方法是调整一下捕获的内容:
([\w\W][\w\W]<%s>)[\w\W]([\w\W])' 然后用 group1 + mode + group2 来替换。