12) Analyser un texte avec les expressions régulières

Trouver tous les liens d’une page web, ou les images qu’elle contient, trouver tous les mots de plus de 6 lettres d’un texte ou tout ceux commençant par une majuscule, voilà entre autres ce que peut faire une expression régulière.

Précédent | 13/16 | Suivant

Les expressions régulières ont été créées dans le but d’identifier et d’extraire des portions d’un texte, sur base d’un pattern, c’est à dire une disposition particulière. La plupart des langages de programmation intègrent la gestion des expressions régulières : javascript, php, c++ et java, donc Processing aussi.

Un exemple frappant : l’adresse mail

Comment savoir si une adresse mail est correctement écrite ? C’est un test effectué dans les formulaires d’inscription, et qui ne peut se faire qu’avec une expression régulière. Il existe des milliards d’adresse mail, mais elles sont toutes structurées de la même manière :
Un nombre indéfini de lettres minuscules et de chiffres, de point et de tirets bas (le nom)
suivi d’un arobase
suivi d’un nombre indéfini de lettres minuscules et de chiffres, de point et de tirets bas (le serveur)
d’un point
et d’un groupe de deux ou trois lettres

Une expression régulière permet de voir si un texte réponde à cette structure particulière, que l’on appelle du coup "pattern".

Pour voir si un texte correspond à un pattern, il faut connaitre la syntaxe générale des expressions régulière, et la manière particulière au langage de programmation de l’appliquer. C’est la que ça se complique un peu évidemment.

En processing, on peut opérer un test avec la fonction match() :

String mail="georges.dugenou@superserveur.com";

String expression="^([_A-Za-z0-9-]+)\\.([_A-Za-z0-9-]+)*@([A-Za-z0-9\\-]+)*\\.([A-Za-z]{2,})$";

String[] test = match(mail, expression);
if (test != null) {
 // si test n'est pas vide, c'est que c'est ok
 println(mail + " est ok");
 println("contenu de la variable test :");
 println(test);
} else {
   println(mail + " n'est pas ok");
}

La fonction match renvoie une variable tableau sur base de son test, qui est de chercher l’expression dans le texte qui lui est donné.
Pourquoi un tableau et pas un un simple "oui" ou "non" ? Parce qu’on peut extraire une ou plusieurs parties du texte avec match(), par exemple ici le nom, prenom de l’adresse et le nom du serveur. Ce script écrit le réultat de la variable test dans la console, comme suit :

georges.dugenou@superserveur.com est ok
contenu de la variable test :
[0] "georges.dugenou@superserveur.com"
[1] "georges"
[2] "dugenou"
[3] "superserveur"
[4] "com"

Les portions de textes sont désignées dans l’expression régulière par les parenthèses, appelées "parenthèses capturantes". Dans cet exemple il y en a 4. L’array "test" renvoie 5 textes : le premier est le contenu total du match, les 4 autres le contenu des parenthèses capturantes.

Puissantes mais difficile à lire

Les expressions régulières peuvent être très compliquées à lire, car elles peuvent être très précises. Je ne peux pas donner un didacticiel complet ici, je recommanderais donc d’aller voir pour débuter les fonctions de processing match() et matchAll() sur le site de processing, ainsi que replace() et replaceAll(), qui ne sont pas documentée sur Processing mais peuvent être utilisée car elles appartiennent à java. On pourra aussi lire lapage de Daniel Shiffman sur le sujet.

Exemples pour le html : extraire le body

Voici un code permettant d’extraire uniquement le contenu du body. Remarquez qu’il emploie une syntaxe particulière et importe une librairie java permettant de la construction d’expressions régulières un peu plus complex (encore). Ici, le code fait en sorte de trouver le body mais s’il est écrit Body ou BODY, la recherche étant insensible à la casse.

import java.util.regex.*;
String fichier="http://arts-numeriques.codedrops.net"; // nom du fichier texte
String[] texte;

void setup() {
 String[] base=loadStrings(fichier);
 println(base);
 String texteunique=join(base, "");

 // ne prendre que le contenu du body
 Pattern p = Pattern.compile(".*<body[^>]*>(.*)</body>.*", Pattern.CASE_INSENSITIVE);
 Matcher m = p.matcher(texteunique);
 String lebody = m.replaceAll("$1 ");

 println(" le resultat \n"+lebody);

Exemples pour le html : extraire les sources des images

Exemple plus probablement utile : récupérer les sources des images présentes dans une page web. Cette fonction utilise la commande matchAll, qui renvoie un tableau à deux dimensions.

// récupérer les adresses des images dans une page web
String fichier="http://arts-numeriques.codedrops.net"; // nom du fichier texte

void setup() {
 String[] base=loadStrings(fichier);
 println(base);
 String texteunique=join(base, "");

 // ne prendre que les tags image
 String regex = "<img.*?src=[\"'](.+?)[\"'].*?>";
 String[][] lesimages = matchAll(texteunique, regex);
 for (int i = 0; i < lesimages.length; i++) {
   println("une image : " + lesimages[i][1]);
 }

Ne pas pleurer

Sachez que la construction d’expressions régulières demande une gymnastique de l’esprit, et que se tromper est monnaie courante. Des millions de pages web de codeurs éplorés en atteste. Faites donc des recherches et des tests en série pour obtenir le résultat escompté...

Pour java, il existe un didacticiel autour des expressions régulières ici.