Nos amies les expressions régulières (ou regex pour les intimes)

Vous ne savez franchement pas à quoi ce truc au nom bizarre pourrait bien vous servir ?
Vous en avez déjà entendu parlé, mais cela reste un grand mystère pour vous ?
Vous avez testé et vous êtes arraché les cheveux ?
Vous voulez juste savoir ce que c’est !

Bienvenu sur ce billet 😃

Vous voulez un cours complet, vous voulez vous perfectionner, vous chercher de l’aide spécifique : passez votre chemin, fouillez la toile qui regorge de ressources en tout genre ou bien adressez vous à un forum ou à une mailing liste spécialisée !

Ce billet est organisé en 3 parties : Ce que les regex peuvent faire, Ce que les regex ne peuvent pas faire et En quoi cela peut nous être utile ? Un cas exemple. (l’exemple arrive à la fin car, sans avoir lu le début, j’ai eu peur de vous perdre définitivement…)

Ce que les regex peuvent faire

En gros, elles permettent de capter des motifs prédéfinis plus ou moins précis. Elles permettent de faire des rechercher-remplacer avancé.

Comment ? Les regex sont utilisables sur pleins de logiciels dont Oxygen, Libre Office (et ses équivalents), etc. En général, il faut aller dans le sous-menu “Recherche” ou “Remplacer” et cocher une case qui active l’utilisation des expressions régulières.

Exemple :

  • recherche “classique” : chercher “marcheur(vivre à Grenoble, ça forge les exemples !) dans un texte renverra toutes les occurences de “marcheur” et (en général) d’autres choses comme “marcheurs” (ça s’est plutôt pratique), “marcheur” (ça, c’est plutôt en trop : on parle de bruit), mais ne renverra pas “marcheuse” (et ça c’est plutôt dommage : on parle de silence).
  • recherche par motif, grâce aux regex, on peut chercher “début de mot + "marcheu" + "r" ou "se" + éventuellement un "s" ». Selon le formalisme (dépend du logiciel que vous utilisez), cela peut s’écrire de différents façons, par exemple : “\bmarcheu(r|se)s?” [ \b : frontière de mot ; (A|B) : A ou B ; A? : 0 ou 1 fois A (autrement dit A est optionnel) ]

Et il existe moultes autres possibilités. Par exemple…

Autour des crochets :

  • si je cherche des mots qui commencent par “X”, “Y” ou “Z”, j’utiliserai la syntaxe \b[XYZ]
  • si je cherche au contraire des mots qui NE commencent PAS par “X”, “Y” ou “Z”, j’ajouterai un ^” dans les crochets : \b[^XYZ]
  • si je cherche des mots tout en majuscules, j’écrirai : \b[A-Z]\b ([A-Z] désigne l’ensemble des lettres de A à Z ; on peut écrire [A-F] pour avoir toutes les lettres de A à F ou encore [α-ε] pour les lettres α, β, γ, δ, ε (à ne pas confondre avec [αε], sans le tiret -, qui désigne uniquement les lettres α et ε vous suivez toujours ?)
    • Il existe des “mots spéciaux” pour désigner des ensembles de caractères. Plus efficaces que ce que je viens d’indiquer car ils gèrent aussi les accents par exemple. Ainsi, [:alpha:] désigne les lettres (majuscules ou minuscules), [:upper:] ne désigne que les majuscules et [:lower:] … suspens… les minuscules. Il existe aussi des mots spéciaux pour les chiffres, la ponctuation, les espaces… (pour en savoir plus : https://en.wikibooks.org/wiki/Regular_Expressions/POSIX_Basic_Regular_Expressions#Character_classes)
  • si je cherche 1 ou plusieurs fois un caractère (“a” par exemple), j’utiliserai a+” (dans “ah !” et “aaah !”)
  • si je cherche 0 ou plusieurs fois un caractère (“a” par exemple), j’utiliserai a*” (dans “ah !”, “aaah !” et même “oh !” qui n’en contient pas)
  • si je cherche 0 ou 1 fois un caractère (“a” par exemple), j’utiliserai a? (dans “ah !”, “oh !”, mais pas “aaah !” qui en contient plus d’un)
  • si je cherche 3 à 6 fois un caractère (“a” par exemple), j’utiliserai a{3-6}
  • si je cherche au moins 3 fois un caractère (“a” par exemple), j’utiliserai a{3-}

Autour des caractères dit “échappés” :

  • \b : on l’a déjà vu, \b capte les frontières de mots et permet de désigner le début ou la fin d’un mot. Écrire “\” avant le “b” permet de dire : je ne cherche pas la lettre “b“, mais bel et bien quelque chose de spécifique : la frontière de mot
  • \t cherche les tabulations
  • \n cherche un passage à la ligne
  • \. cherche le point “.“. Hé oui, sans l’anti-slash “\“, “.” désigne “n’importe quel caractère”. Une sorte de super joker !
  • \( : dans la même veine, \( permet de chercher une parenthèse ouvrante, alors que sans l’échappement “(” est utilisé comme nous l’avons vu précédemment pour débuter une alternative (lac|cascade) qui désigne “lac ou cascade” c’est l’été… il fait chaud… 🚣

Autour de la notion de “ligne de texte” :

  • ^Chartreuse$ permet de repérer les lignes qui ne contiennent que le mot “Chartreuse”.
    • $ désigne la fin d’une ligne
    • ^ désigne le début d’une ligne (quoi ?! On n’avait pas vu que dans \b[^XYZ] le ^ permettait d’exclure des caractères (un mot qui ne commence pas par X, Y ni Z) !!! Euh… si, si ! Mais là, je parle de ^ hors des crochets… faut être accroché !

STOP ! 🤪

Je me le suis promis de ne pas faire de ce post un cours et je suis déjà allée bien trop loin. Il y a largement ce qu’il faut dans l’existant (des cours, des tutos, des vidéos, des exemples… tout ce que vous voudrez !) Alors je m’arrête là. Je voulais simplement vous faire entrevoir le monde merveilleux des expresions régulières !

Mais avant de conclure : deux points à aborder : ce que les Regex ne peuvent pas faire et en quoi cela peut nous être utile à nous dans le monde des humanités numériques (pas, peu ou très connaisseurs en informatiques).

Ce que les Regex ne peuvent pas faire

Juste au cas où…

Je vous déconseille fortement d’utiliser les regex
sur du XML ou du HTML.
Elles ne sont pas faites pour !

Entendons-nous bien :

  • pourquoi pas : pour travailler sur du texte dans les balises !
  • mais… pour travailler sur les balises en elle-même, c’est carrément terrain glissant  :
    • d’un point de vue mathématique, ce n’est tout simplement pas fait pour ;
    • intuitivement, pensez que les balises, ça va par deux et en plus tout cela est hiérarchique donc… ça semble peut adapté
  • la solution ? pour manipuler du XML, passez plutôt à XSLT qui lui même peut intégrer des regex ! Youpi !!!

 

En quoi cela peut nous être utile ? Un cas exemple.

Dans le cadre du projet TAF on bosse dur ! Pffuuu le jeu de mot nuuul… Bref pour Traduire Aristophe en France, nous souhaitons nous doter d’un ensemble de textes en TEI. Pour rappel/info, il s’agit d’oeuvre théâtrale (ça a de l’importance). Nous avons scanné des ouvrages, utilisé un logiciel d’océrisation (reconnaissance optique des caractères) pour disposer d’une version textuelle (plus ou moins propre, soyons honnêtes… mais enfin, là n’est pas mon discours 😉 ),  puis voulu structuré le tout en TEI.

OR… le théâtre est un texte structuré de façon assez spécifique. On trouve notamment les noms des personnages qui prennent la parole seuls sur une ligne dédiée et en général, intégralement en majuscules. Une expression régulière peut donc nous aider à les repérer et à les encoder de façon semi-automatique :

  • ^[:upper:]{3-}$ repère début de ligne + majuscules au moins 3 fois + fin de ligne

Nous utilisons bien d’autres regex dont :

  • ^[0-9]+$ qui repère des lignes qui ne contiennent que des chifres (des entêtes de page par exemple)

 

Je m’arrête là pour cette petit intro
et je vous souhaite de bien vous amuser !

Si vous avez suivi jusqu’à la fin, 👏 je vous tire mon chapeau franchement 👏 car les regex, c’est un monde merveilleux, mais c’est aussi un labyrinthe passablement sadique et pas que sur les bords !

Si vous êtes perdu : c’est que j’ai raté mon coup, faut être honnête… ce n’est pas votre faute j’espère au moins que cela vous aura permis de comprendre les grands principes et ce que les regex peuvent permettre.

N’hésitez pas dans tous les cas à réagir dans les commentaires !

 


Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.