2009-05-20 5 views
0

J'ai besoin pour analyser un fichier de configuration qui ressemble à ceci (simplifié):Puis-je utiliser re.sub (ou regexobject.sub) pour remplacer du texte dans un sous-groupe?

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

Mon objectif est d'être en mesure de modifier les paramètres spécifiques à un lien particulier, mais je vais avoir du mal à obtenir une substitution pour fonctionner correctement . J'ai un regex qui peut isoler une valeur de paramètre sur un lien spécifique, où la valeur est contenue dans le groupe de capture 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) 

Ainsi,

print re.search(final_regex, f_read).group(1) 

impressions ipsec

Les exemples dans le regex howto tous semblent supposer que l'on veut utiliser le groupe de capture dans le remplacement, mais ce que je dois faire est de remplacer le groupe de capture lui-même (par exemple changer le mode Link1 d'ipsec en udp).

+0

Modification du regex tel qu'il existe maintenant deux groupes de capture bracketing le texte que je dois changer, puis y compris ces deux groupes la chaîne de remplacement a travaillé. –

+0

Je suis curieux de savoir pourquoi n'utilisez-vous pas la librairie xml au lieu de reges? –

+0

Un couple de facteurs, y compris la connaissance limitée de XML de ma part et la suggestion par d'autres développeurs que je respecte qu'une regex pourrait être le moyen le plus rapide pour moi de résoudre le problème. Cela dit, je pourrais aller avec l'option BeautifulSoup, car il semble être relativement simple à mettre en œuvre. –

Répondre

0

pas sûr que je le ferais de cette façon, mais le moyen le plus rapide serait de transférer les captures:

([\ w \ W] [\ w \ W] <% s>) [ \ w \ W] ([\ w \ W]) » et remplacer par groupe1 mode + + group2

+0

Merci, cela m'a donné l'indice dont j'avais besoin. –

1

supposant que votre link_regex est correcte, vous pouvez ajouter des parenthèses comme ceci:

(<link [\w\W]+ %s>[\w\W]*[\w\W]*<%s>)([\w\W]*)(</%s>[\w\W]*</link>) 

et alors vous pourriez faire:

p = re.compile(link_regex) 
replacement = 'foo' 
print p.sub(r'\g<1>' + replacement + r'\g<3>' , f_read) 
+0

C'est ce que j'ai fini par faire. –

6

Je dois vous donner l'obligation: "n'utilisez pas d'expressions régulières pour le faire."

Découvrez comment très facilement, il est génial de le faire avec BeautifulSoup, par exemple:

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

En regardant votre expression régulière, je ne peux pas vraiment dire si c'est exactement ce que vous vouliez faire, mais peu importe ce que vous voulez faire, utiliser une librairie comme BeautifulSoup est beaucoup, beaucoup, mieux que d'essayer de patcher une expression régulière ensemble. Je recommande fortement d'aller dans cette voie si possible.

+0

ou si c'est du xml standard, il peut juste utiliser du xml lib comme elementTree pour le modifier, je ne vois vraiment pas l'utilisation de reg ex ici. –

2

Cela ressemble à XML valide, dans ce cas, vous n'avez pas besoin BeautifulSoup, certainement pas l'expression régulière, il suffit de charger XML en utilisant une bonne bibliothèque XML, le modifier et l'imprimer, est une approche ici en utilisant 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) 

Il changera tous les éléments de mode à udp, c'est la sortie:

<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> 
Questions connexes