2009-05-20 9 views
4

En résumé, j'ai deux motifs regex. Un motif correspond à des éléments que je veux remplacer et l'autre modèle correspond à un cas particulier de ces motifs qui ne doivent pas être remplacés. Pour un exemple simple, imaginez que le premier est "\ {. * \}" Et le second "\ {\ {. * \} \}". Alors "{this}" devrait être remplacé, mais "{{this}}" ne devrait pas. Existe-t-il un moyen facile de prendre une chaîne et de dire "substituer toutes les instances de la première chaîne par" bonjour "tant qu'elle ne correspond pas à la deuxième chaîne"? En d'autres termes, existe-t-il un moyen de créer facilement une regex qui «correspond facilement à la première chaîne mais pas à la seconde» sans modifier la première chaîne? Je sais que je pourrais modifier ma première regex à la main pour ne jamais correspondre aux instances de la seconde, mais comme la première regex devient plus complexe, cela devient très difficile.Substituer une regex seulement quand elle ne correspond pas à une autre regex (Python)

Répondre

4

Vous pouvez donner remplacer une fonction (reference)

Mais assurez-vous que la première regex contient le second. Ceci est juste un exemple:

regex1 = re.compile('\{.*\}') 
regex2 = re.compile('\{\{.*\}\}') 

def replace(match): 
    match = match.group(0) 
    if regex2.match(match): 
     return match 
    return 'replacement' 


regex1.sub(replace, data) 
1

Vous pouvez remplacer toutes les instances {} par votre chaîne de remplacement (ce qui inclut les {{}}), puis remplacer les {{}} par une référence arrière (en remplaçant le premier par les données d'origine) - alors seulement les instances {} auraient changé.

+0

Pourriez-vous me donner un exemple de la façon de faire cela en python? Je ne suis pas sûr de comprendre. Merci! – So8res

+0

Je peux dans environ une heure, mais pas maintenant, désolé ... –

0

Il me semble sous-optimal pour correspondre contre deux regexes différentes quand ce que vous cherchez est vraiment un modèle. Pour illustrer:

import re 
foo = "{{this}}" 
bar = "{that}" 
re.match("\{[^\{].*[^\}]\}", foo) # gives you nothing 
re.match("\{[^\{].*[^\}]\}", bar) # gives you a match object 

Donc, c'est vraiment votre regex qui pourrait être un peu plus précis.

+0

C'est vrai, mais Nate a donné un exemple imaginaire simple. Ce n'est pas toujours le cas. –

6

L'utilisation négative look-ahead/derrière l'affirmation

pattern = re.compile("(?<!\{)\{(?!\{).*?(?<!\})\}(?!\})") 
pattern.sub("hello", input_string) 

look-ahead négatif/derrière l'affirmation vous permet de comparer contre plus de la chaîne, mais ne sont pas considérés comme en utilisant une partie de la chaîne pour le match . Il y a aussi un regard normal devant/derrière une assertion qui fera correspondre la chaîne seulement si la chaîne est suivie/précédée par le motif donné.

C'est un peu déroutant à la recherche, le voici en morceaux:

"(?<!\{)" #Not preceded by a { 
"\{"  #A { 
"(?!\{)" #Not followed by a { 
".*?"  #Any character(s) (non-greedy) 
"(?<!\})" #Not preceded by a } (in reference to the next character) 
"\}"  #A } 
"(?!\})" #Not followed by a } 

Donc, nous recherchons un {sans autre {est autour d'elle, suivi de quelques caractères, suivi d'un} sans autre} autour de lui. En utilisant l'assertion anticipée négative/derrière l'assertion, nous la condensons en une seule expression régulière qui ne correspondra que {} à n'importe quel élément de la chaîne.

Notez également que * est un opérateur gourmand. Il correspondra autant que possible. Si vous utilisez "\{.*\}" et qu'il y a plus d'un bloc {} dans le texte, tout sera pris en compte.

"Ceci est un exemple de texte {de block1} plus de texte, regardez-moi disparais {block2} encore plus texte"

devient

« Ceci est un exemple de texte bonjour encore plus texte »

au lieu de

« Ceci est un exemple de texte bonjour texte plus, regardez-moi disparais bonjour encore plus texte »

Pour obtenir la sortie correcte, nous devons le faire non gourmand en ajoutant un?.

Les docs python font un bon travail de présentation de la bibliothèque re, mais la seule façon d'apprendre est d'expérimenter.

Questions connexes