繁体   English   中英

我可以使用re.sub(或regexobject.sub)替换子组中的文本吗?

[英]Can I use re.sub (or regexobject.sub) to replace text in a subgroup?

我需要解析一个看起来像这样的配置文件(简化):

<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)。

我必须给你一个强制性:“不要使用正则表达式来做到这一点。”

查看使用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之类的库都比尝试将正则表达式拼凑在一起要好得多。 如果可能,我强烈建议您走这条路线。

这看起来像有效的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>

假设您的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)

不知道我会那样做,但是最快的方法是转移捕获:

([\\ w \\ W] [\\ w \\ W] <%s>)[\\ w \\ W] ([\\ w \\ W] )'并替换为group1 + mode + group2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM