Programmation Python/Regex

Un livre de Wikilivres.
Aller à : navigation, rechercher


Les expressions régulières en Python nécessitent le module re[1].

Syntaxe[modifier | modifier le wikicode]

Expressions rationnelles courantes
Caractère Type Explication
. Point n'importe quel caractère
[...] classe de caractères tous les caractères énumérés dans la classe
[^...] classe complémentée Tous les caractères sauf ceux énumérés
^ circonflexe marque le début de la chaine, la ligne...
$ dollar marque la fin d'une chaine, ligne...
| barre verticale alternative - ou reconnaît l'un ou l'autre
(...) parenthèse utilisée pour limiter la portée d'un masque ou de l'alternative
* astérisque 0, 1 ou plusieurs occurrences
+ le plus 1 ou plusieurs occurrence
 ? interrogation 0 ou 1 occurrence

Remarques :

  • Les caractères de débuts et fin de chaines ne fonctionnent pas dans [].
  • Les opérateurs * et + sont toujours avides, pour qu'ils laissent la priorité il faut leur apposer un ? à leur suite.

De plus, Python propose :

  • la négation (?!). Attention : il faut toujours la faire suivre de .*. Exemple pour avoir toutes les balises HTML sauf "body" : <(?!body).*>.
  • Ignorer le groupe de capture dans la numérotation (?:)
  • negative lookbehind (?<!)
  • positive lookbehind (?<=)
  • negative lookahead (?!)
  • positive lookahead (?=)

Types[modifier | modifier le wikicode]

Les types de caractères sont représentés par :

  • \n : fin de ligne.
  • \b : fin de mot.
  • \w : caractère alphanumérique.
  • \d : caractère numérique.
  • \s : espace.

Certains ont leurs opposés en capitale :

  • \W : caractère non-alphanumérique.
  • \D : caractère non-numérique.
  • \S : non-espace.

Recherche[modifier | modifier le wikicode]

  • compile() renvoie None si l'expression rationnelle n'est pas trouvée dans la chaine.
  • search() renvoie la position des chaines recherchées.
#!/usr/bin/env python
import re
chaine = "Test regex Python pour Wikibooks francophone."
if re.compile('Wikibooks').search(chaine):
	print "Position du mot Wikibooks : "
	print re.search(u'Wikibooks', chaine).start()
        # Affiche "23"
        print re.search(u'Wikibooks', chaine).end()
        # Affiche "32"
  • findall() trouve toutes les correspondances dans un tableau.
  • finditer() trouve toutes les correspondances dans un itérateur.
#!/usr/bin/env python
# Affiche tous les mots qui commencent par "Wiki"
import re
chaine = "Wikilivre regex Python pour Wikibooks francophone."
print (re.findall(r"Wiki\w+", chaine))
# Affiche ['Wikilivre', 'Wikibooks']


Les parenthèses imbriquées permettent d'indiquer des mots facultatifs au sein d'un groupe de capture. Ex :

#!/usr/bin/env python
# Trouve à un mot prêt
import re
chaine = "Wikilivre regex Python pour Wikibooks francophone."

regex = ur'(Python pour Wikibooks)'
print re.search(regex, chaine).start() # 16

regex = ur'(Python (pour )*Wikibooks)'
print re.search(regex, chaine).start() # 16

regex = ur'(Python pour (les )*Wikibooks)'
print re.search(regex, chaine).start() # 16

Les méthodes de la bibliothèque regex sont limitées à une seule ligne par défaut, pour étendre cette limite il faut les appeler avec le paramètre 2 : re.MULTILINE.

En multiligne, un "^" en début de re.search() considérera le début de chaque ligne. Pour partir uniquement du début de la chaine, utiliser "re.match()"[2].

Pour accéder aux résultats des groupes de capture, utiliser group() en partant de 1 :

#!/usr/bin/env python
import re
chaine = "Wikilivre regex Python pour Wikibooks francophone."
s = re.search(ur'(Wiki[a-z]*).*(Wiki[a-z]*)', chaine)
if s:
    print s.group(0)
    # Affiche 'Wikilivre regex Python pour Wikibooks'
    print s.group(1)
    # Affiche 'Wikilivre'
    print s.group(2)
    # Affiche 'Wikibooks'

De même, pour que .* englobe les retours à la ligne, il faut appeler le paramètre 2 : re.DOTALL. Exemple :

 if re.search(regex, text, re.MULTILINE| re.DOTALL):

Remplacement[modifier | modifier le wikicode]

#!/usr/bin/env python
# Remplace tous les espaces par des underscores
import re
chaine = "Test regex Python pour Wikibooks francophone."
chaineTriee = re.sub(r' ', "_", chaine)
print chaineTriee
# Affiche "Test_regex_Python_pour_Wikibooks_francophone."

Pour remplacer certains éléments en conservant ceux placés entre parenthèses, il faut les désigner par \1, \2, \3...

#!/usr/bin/env python
# Ajoute des guillemets à tous les mots suivent "livre"
import re
chaine = "Test regex Python pour le livre Python de Wikibooks francophone."
chaineTriee = re.sub(r'(.*)livre (\w+)(.*)', r'\1livre "\2"\3', chaine)
print chaineTriee
# Affiche "Test regex Python pour le livre "Python" de Wikibooks francophone."

Remarque : si les paramètres (\1, \2...) sont remplacés par le symbole �, vérifier que la chaine regex est bien encodée avec r.

link={{{link}}}Attention !

Les différents contenus d'un même groupe de capture sont remplacés par le premier \1. Pour éviter cela, il faut les traiter un par un avec "finditer()".

Exemple : remplacement de la balise "font color=" par "span style=font-size:".

    text = ur'<font color=green>Vert</font> / <font color=red>rouge</font>'
    regex = ur'<font color=([^>]*)>'
    pattern = re.compile(regex, re.UNICODE)
    for match in pattern.finditer(text):
        print u'Remplacement de ' + match.group(0) + u' par <span style="font-color:' + match.group(1) + u'">'
        text = text.replace(match.group(0), u'<span style="font-color:' + match.group(1) + u'">')
        text = text.replace('</font>', u'</span>')
    raw_input(text)

Exemples de formules[modifier | modifier le wikicode]

  • Récupérer le premier modèle 1 wiki non imbriquée dans un autre modèle :
page = u'{{Modèle2|Paramètre2, {{Modèle1|Paramètre3}} }}, {{Modèle1|Paramètre4}}'
regex = ur'({{(.*?)}}|.)*[^}]*'
raw_input(re.sub(regex, ur'\2', page).encode(config.console_encoding, 'replace'))

Pour indiquer un nombre précis d'occurrences, utiliser "{nombre}". Ex :

#!/usr/bin/env python
import re
chaine = 'w.1, ww.2, www.3, wwww.4'
print re.sub(ur' w{3}\.', ' http://www.', chaine)
w.1, ww.2, http://www.3, wwww.4

Idem pour une plage de nombres : {min,max}.

link={{{link}}}Attention !

Quand on injecte une variable dans un pattern, il faut échapper ses caractères interprétables avec re.escape().

Références[modifier | modifier le wikicode]