Can re.sub (or regexobject.sub) be used to replace text in a subgroup?
I need to parse a config file that looks like this (simplified):
<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>
My goal is to be able to change the options related to a specific link, but I'm having trouble getting the substitution to work properly. I have a regex that can isolate a parameter value by a specific reference where the value is contained in capturing group 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)
In this way,
print re.search(final_regex, f_read).group(1)
IPSec printing
The regex howto examples all seem to suggest that you want to use the capture group in replacement, but what I need to do is replace the capture group itself (e.g. changing Link1 mode from ipsec to udp).
a source to share
I have to give you a must: "don't use regular expressions for this."
See how easy it is to do this with BeautifulSoup , for example:
>>> 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>
Looking at your regex, I can't tell if that's really what you wanted to do, but whatever you do, using a library like BeautifulSoup is much, much better than patching the regex together. I highly recommend going this route if possible.
a source to share
This looks like valid XML, in which case you don't need BeautifulSoup, definitely not a regex, just load the XML with any good XML library, edit it and print it, here is the approach using 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)
It will change all mode elements to udp
, this is the result:
<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>
a source to share