Могу ли я использовать re.sub (или regexobject.sub) для замены текста в подгруппе? - PullRequest
0 голосов
/ 20 мая 2009

Мне нужно проанализировать файл конфигурации, который выглядит следующим образом (упрощенно):

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

печать * 1010 IPSec *

Примеры в regex howto все, кажется, предполагают, что кто-то хочет использовать группу захвата в замене, но мне нужно заменить саму группу захвата (например, изменить режим Link1 ipsec to udp).

Ответы [ 4 ]

6 голосов
/ 20 мая 2009

Я должен дать вам обязательное: «не используйте регулярные выражения для этого».

Посмотрите, как легко это сделать с помощью 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, намного, намного лучше, чем попытка исправить обычное выражение. выражение вместе Я настоятельно рекомендую идти по этому маршруту, если это возможно.

2 голосов
/ 20 мая 2009

Это похоже на действительный 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>
1 голос
/ 20 мая 2009

Предполагая, что ваш 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)
0 голосов
/ 20 мая 2009

не уверен, что я сделал бы это таким образом, но самый быстрый способ - сдвинуть снимки:

([\ w \ W] [\ w \ W] <% s>) [\ w \ W] ([\ w \ W] ) 'и заменить с group1 + mode + group2

...