我需要解析一个看起来像这样的配置文件(简化):
<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
regex howto中的示例似乎都假设有人想在替换中使用捕获组,但我需要做的是替换捕获组本身(例如将Link1模式从ipsec更改为udp )。
答案 0 :(得分: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这样的库比试图修正常规表更好一起表达。如果可能的话,我强烈建议你走这条路。
答案 1 :(得分: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)
它会将所有模式元素更改为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>
答案 2 :(得分:1)
假设你的link_regex是正确的,你可以像这样添加括号:
(<link [\w\W]+ %s>[\w\W]*[\w\W]*<%s>)([\w\W]*)(</%s>[\w\W]*</link>)
然后你可以这样做:
p = re.compile(link_regex)
replacement = 'foo'
print p.sub(r'\g<1>' + replacement + r'\g<3>' , f_read)
答案 3 :(得分:0)
不确定我会这样做,但最快捷的方法是改变捕捉:
([\ W \ W]的 [\ W \ W] &LT;%S取代;)[\ W \ W]的([\ W \ W] ) '并替换为group1 + mode + group2