Utilisation des expressions régulières en Java

Les expressions régulières en java

Ce document explique comment utiliser les expressions régulières en java. Il s’inspire de la documentation de la classe Pattern sur le site d’oracle.

Qu’est ce qu’une expression régulière ?

Une expression régulière ou rationnelle est une chaine de caractères qui décrit un ensemble de chaines de caractères.

Par exemple l’expression régulière [0-9 * [a-z] décrit l’ensemble des chaines de caractères composées d’un chiffre et d’une lettre.

A quoi servent les expressions régulières ?

Les expressions régulières ont de nombreuses utilités en informatique, elles servent principalement pour réaliser :

  • des filtres : ne conserver que certaines lignes d’un fichier texte : par exemples que les lignes de la forme variable=valeur.
  • des contrôles : vérifier qu’une donnée entrée par un utilisateur a bien le format d’une adresse ip par exemple.
  • des substitutions : remplacer un motif par une chaine de caractères précise : par exemple, remplacer les majuscules par des minuscules.
  • des découpages : récupérer une partie d’une chaine de caractères par exemple une date placée dans une chaine de caractères. Ou bien découper une ligne par rapport aux « ; » dans le cas d’un fichier .csv.

Créer une expression régulière

Pour créer une expression régulière en java, on respecte une certaine syntaxe qui est décrite dans la documentation officielle sur le site d’oracle : classe Pattern. Je décris ci-dessous les principaux caractères utilisés.

Composantes d’une expression régulières

Les caractères

X         Le caractère X

\\        Le caractère \

\t         Le caractère tabulation

\n         Le caractère nouvelle ligne

\r         Le caractère retour chariot

\f         Le caractère saut de page

Exemple : AB\tCD représente la chaine de caractère AB suivi d’une tabulation suivi de CD.

Les classes de caractères

[abc *          Les caractères a, b ou c

[^abc]         Les caractères qui ne sont pas a, b ou c

[a-z]         Un caractère de a à z

[a-zA-Z]     Un caractère de a à z minuscule ou majuscule

[0-9]         Un caractère numérique

Exemple : [0-9][a-z] représente une chaine de caractères constituée d’un chiffre puis d’une lettre.

Il faut noter qu’il existe une différence entre ab qui représente la chaine de caractère « ab » de [ab * qui représente soit la chaine de caractère « a » soit la chaine de caractères « b ».

Les classes de caractères prédéfinies

        Un caractère quelconque

\d         Un caractère numérique : [0-9 *

\D         Un caractère non numérique : [^0-9 *

\s         Un carctère blanc : [ \t\n\x0B\f\r *

\S         Un caractère non blanc : [^\s *

Classes de caractères POSIX

\p{Lower}     Une misnuscule : [a-z *

\p{Upper}     Une majuscule :[A-Z *

\p{Alpha}     Un caractère alphabétique : [\p{Lower}\p{Upper} *

\p{Digit}     Un chiffre : [0-9 *

\p{Alnum}     Un caractère alphanumérique : [\p{Alpha}\p{Digit} *

\p{Punct}     Ponctionation : !"#$%&'()*+,-./:;<=>?@[\ * ^_'{|}~

\p{Blank}     Espace ou tabulation : [ \t *

\p{XDigit}     Un caractère hexadécimal: [0-9a-fA-F *

\p{Space}     Un caractère blanc : [ \t\n\x0B\f\r *

Les caractères de répétition

X?         X une fois ou zéro fois

X*         X zéro ou plusieurs fois

X+         X une fois au moins (XX*)

X{n}         X n fois

X{n,}         X, au moins n fois

X{n,m}         X entre n et m fois

Opérateurs logiques

XY         X suivi de Y

X|Y         X ou Y

Exemples

Expression régulière correspondant à une adresse IP

Une adresse IP est de la forme suivante : 255.255.0.1 ou bien 127.0.0.1, son format est donc :

Un à trois chiffres, point, un à trois chiffres, point, un à trois chiffres, point, un à trois chiffres.

L’expression régulière correspondante est donc :

[0-9 * {1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

ou

\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}

On peut également utiliser une expression régulière plus simple si on ne souhaite pas vérifier que le nombre de chiffres est bien compris entre un et trois :

\d+\.\d+\.\d+\.\d+

Remarque : Le point s’écrit \. car « . » est un caractère qui signifie « un caractère quelconque ». Le \ précédent le . sert à indiquer qu’il ne faut pas interpréter le point comme une expression régulière.

Expression régulière correspondant à une date

Une date au format 29 février 2012 suit le motif suivant :

Un ou deux chiffres, un espace, un nombre indéfini de lettres, un espace puis quatre chiffres.

L’expression régulière associée est donc :

[0-9 * {1,2} [a-z]+ [0-9]{4}

ou

\d{1,2} \p{Lower}+ \d{4}

Expression régulière d’une ligne de la commande dir

La commande dos « dir » permet de lister les fichiers d’un répertoire. La sortie de cette commande se présente sous la forme suivante :

26/01/2012 11:45 <REP> dossier

26/01/2012 11:45 fichier.txt

Le format est donc : la date suivie de plusieurs espaces, suivie de l’heure, suivie de plusieurs espaces, ensuite, si le fichier est un dossier, on trouve la chaine de caractère <REP> et rien sinon, et pour finir, le nom du fichier ou du dossier.

L’expression régulière correspondante est

\d{1,2}/\d{1,2}/\d{1,2}\p{Space}*\d{1,2} :\d{1,2}\p{Space}*\p{Upper}*\p{Space}*\p{Alpha}*

Utilisation avec java

Une première remarque est que le caractère \ a un sens pour java, il faut donc le doubler dans l’écriture des expressions régulières pour qu’il ne soit pas interprété par java. Par exemple, on écrira \\. à la place de \.

Les méthodes

La méthode matches de la classe String

public boolean matches(String regex)

La méthode matches de la classe String permet de savoir si une chaine de caractère respecte une expression régulière. Pour cela, on passe l’expression régulière en paramètre de la méthode et la méthode retourne true si l’expression régulière est vérifiée par la chaine de caractères.

La méthode replaceAll de String

public String replaceAll(String regex,String replacement)

La méthode replaceAll permet de remplacer toutes les occurrences d’une expression régulière par une expression de remplacement. Cette méthode peut être également appelée en utilisant la méthode replaceAll de la classe Pattern (ici str est le chaine sur laquelle on recherche : Pattern.compile(regex).matcher(str).replaceAll(replacement).

La méthode split de la classe String

public String * split(String regex)

La méthode split permet de découper une chaine de caractères en fonction d’une expression régulière. Le résultat du découpage est retourné dans un tableau.

Si le découpage est fait à l’aide d’un unique caractère (souvent espace ou « ; ») on utilisera plutôt la classe StringTokenizer qui ne permet pas l’utilisation des expressions régulières.

Exemples

Réaliser des filtres

On peut vouloir ne conserver que certaines lignes d’un fichier texte, par exemple si on veut lire le fichier etc/hosts qui contient les correspondances entre les noms d’hôtes et les adresses IP des machines.

Ce fichier peut contenir des commentaires qui sont précédés du caractère #. On pourrait donc penser qu’il suffit de récupérer le premier caractère de la ligne et de le comparer à ‘#’ mais, ce n’est pas si simple.

Une ligne est un commentaire si et seulement si le premier caractère non blanc est un #. Pour s’en sortir sans les expressions régulières, il faudrait donc coder une fonction avec des boucles imbriquées qui serait assez longues et complexes. Une ligne suffit si on utilise les expressions régulières.

Admettons que nous ayons récupéré le contenu du fichier dans une ArrayList et qu’on souhaite extraire une liste contenant uniquement les lignes qui ne sont pas des commentaires :

public static void main(String * args){
List<String> listeInitiale = new ArrayList<String>();
listeInitiale.add("# 102.54.94.97 rhino.acme.com # serveur source");
listeInitiale.add(" # 38.78.63.10 x.acme.com # hôte client x");
listeInitiale.add("");
listeInitiale.add("127.0.0.1 localhost # machine courante");
for(String s : listeInitiale){
if(!s.matches("\\p{Space}*[# * .*") && s.length()>0)
System.out.println(s);
}
}

Réaliser des contrôles

Pour vérifier qu’un champ correspond bien à une adresse ip, on peut utiliser la méthode matches de String comme dans l’exemple précédent

public static void main(String * args){
String champ = "255.255.10.1";
System.out.println(champ.matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));
}

Réaliser des substitutions

Si on veut remplacer tout les espaces multiples d’un fichier par un seul espace, on peut utiliser la méthode rempaceAll avec l’expression régulière \\p{Space}+

   public static void main(String * args){
String test = "1 2 3 4 5 6 7 8 ";
System.out.println(test.replaceAll("\\p{Space}+", " "));
}

Réaliser des découpages de chaines

Pour découper une chaine selon une expression régulière, on utilise la méthode split de la classe String.

Par exemple, si on a un fichier chaque ligne est constituée de différentes informations séparées par une suite de caractères par exemple !@!, ont peut utiliser la méthode split pour récupérer toutes les informations séparément dans un tableau.

Par exemple :


public static void main(String * args){
String test = "Jean Pierre!@!Paul!@!45";
String * infos = test.split("!@!");
System.out.println("Nom : "+infos[1 * +"\nPrénom : "+infos[0]);
}

Récupérer une information dans une chaine

On peut récupérer une information présente dans une chaine de caractère en utilisant les « capturing groups ».

Le principe est simple : il suffit de places des parenthèses autour de la sous expression régulière que l’on souhaite récupérer.

Par exemple : on souhaite récupérer les noms de tous les processus qui s’exécutent sur une machine. Pour cela on lance la commande Dos TASKLIST qui nous donne des informations sur les processus de la manière suivante :

Nomde l'image PID Nom de la session Numéro d'utilisation Utilisation
System Idle Process 0 Console 0 28 Ko
System 4 Console 0 44 Ko
smss.exe 732 Console 0 60 Ko
csrss.exe 796 Console 0 3564 Ko
winlogon.exe 820 Console 0 6456 Ko
services.exe 864 Console 0 3772 Ko

On pourrait récupérer les informations en utilisant le fait que le nom de l’image ne peut pas être plus ongue que 24 caractères. Mais nous allons plutôt utiliser une expression régulière avec capturing group.

L’expression régulière qui décrit cette ligne est :

[^0-9 * +\\p{Space}+[0-9]+.*

On souhaite récupérer la partie [0-9 * +, on va donc placer des parenthèses autour de cette partie et utiliser les méthodes de la classe Pattern pour récupérer le nom de l’image.


public static String recupererNomImage(String ligne){
String res="";
String patternStr = "([^0-9 * +)\\p{Space}+[0-9]+.*";
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(ligne);
boolean matchFound = matcher.find();
if (matchFound && matcher.groupCount()>=1) {
res = matcher.group(1);
}
return res;
}
public static void main(String * args) {
String test="System Idle Process 0 Console 0 28 Ko";
System.out.println(recupererNomImage(test));
}
A voir également
Ce document intitulé « Utilisation des expressions régulières en Java » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous