< Programmation Java

En informatique, une expression régulière ou expression rationnelle ou expression normale ou motif, est une chaîne de caractères, qui décrit, selon une syntaxe précise, un ensemble de chaînes de caractères possibles. Les expressions régulières sont également appelées regex (de l'anglais regular expression). Elles sont issues des théories mathématiques des langages formels. Les expressions régulières sont aujourd’hui utilisées pour la lecture, le contrôle, la modification, et l'analyse de textes ainsi que la manipulation des langues formelles que sont les langages informatiques.

L'exemple d'expression régulière suivant permet de valider qu'une chaîne de caractère correspond à la syntaxe d'un nombre entier non signé, c'est à dire une suite non vide de chiffres :

[0-9]+

En détails :

  • Les crochets spécifient l'ensemble des caractères auquel doit appartenir le caractère courant de la chaîne. Dans cet exemple, l'ensemble est celui des chiffres de 0 à 9 inclus.
  • Le caractère plus indique de répéter le motif précédent au moins une fois (suite non vide).

En Java, la validation d'une chaîne de caractères peut se faire en utilisant la méthode statique matches de la classe java.util.regex.Pattern :

import java.util.regex.*;

public class Example
{
	public static void main(String[] args)
	{
		System.out.println(Pattern.matches("[0-9]+", "12345")); // true
		System.out.println(Pattern.matches("[0-9]+", "12ABC")); // false
	}
}

Syntaxe

Les expressions rationnelles peuvent être analysées et testées via un débogueur en ligne comme https://regex101.com/.

Expressions rationnelles courantes
Caractère Type Explication
. Point n'importe quel caractère
[...] crochets classe de caractères : tous les caractères énumérés dans la classe, avec possibilité de plages dont les bornes sont séparées par "-". Ex : [0-9a-z] pour tout l'alphanumérique en minuscule, ou [0-Z] pour tous les caractères de la table Unicode entre "0" et "Z", c'est-à-dire l'alphanumérique majuscule plus ":;<=>?@"[1].
[^...] crochets et circonflexe 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èses groupe de capture : 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 occurrences
 ? interrogation 0 ou 1 occurrence
{...} accolades comptage : détermine un nombre de caractères remplissant les critères qu'il suit. Ex : a{2} deux occurrences de "a", a{1,10} (sans espace) entre une et dix.
(?P<nom>pattern) named subpattern nomme le résultat d'un groupe de capture par un nom.

Remarques :

  • Les caractères de débuts et fin de chaines (^ et $) ne fonctionnent pas dans [] où ils ont un autre rôle.
  • Les opérateurs * et + sont toujours avides, pour qu'ils laissent la priorité il faut leur apposer un ? à leur suite[2].
Classes de caractères POSIX[3]
Classe Signification
[[:alpha:]] n'importe quelle lettre
[[:digit:]] n'importe quel chiffre
[[:xdigit:]] caractères hexadécimaux
[[:alnum:]] n'importe quelle lettre ou chiffre
[[:space:]] n'importe quel espace blanc
[[:punct:]] n'importe quel signe de ponctuation
[[:lower:]] n'importe quelle lettre en minuscule
[[:upper:]] n'importe quelle lettre capitale
[[:blank:]] espace ou tabulation
[[:graph:]] caractères affichables et imprimables
[[:cntrl:]] caractères d'échappement
[[:print:]] caractères imprimables exceptés ceux de contrôle
Expressions rationnelles Unicode[4]
ExpressionSignification
\ADébut de chaine
\bCaractère de début ou fin de mot
\dChiffre
\DNon chiffre
\nFin de ligne
\\pL, \p{L}, \p{Letter}Lettre (dans tout langage)
\sCaractères espace
\SNon caractères espace
\tTabulation
\wCaractère alphanumérique : lettre, chiffre ou underscore
\WCaractère qui n'est pas lettre, chiffre ou underscore
\XCaractère Unicode
\zFin de chaine

Constructeurs spéciaux : Ces fonctions précèdent l'expression à laquelle elles s'appliquent, et le tout doit être placé entre parenthèses.

  • ?: : groupe non capturant. Ignorer le groupe de capture lors de la numérotation des backreferences. Exemple : ((?:sous-chaine_non_renvoyée|autre).*).
  • ?> : groupe non capturant indépendant.
  • ?<= : positive lookbehind.
  • ?<! : negative lookbehind.
  • ?= : positive lookahead.
  • ?! : negative lookahead. Exclusion d'une chaine. Il faut toujours la faire suivre d'un point. Exemples :
    ((?!sous-chaine_exclue).)
    <(?!body).*> : pour avoir toutes les balises HTML sauf "body".
    début((?!mot_exclu).)*fin[5] : pour rechercher tout ce qui ne contient pas un mot entre deux autres.
    (?!000|666) : pour exclure 000 et 666[6].

Les expressions rationnelles en Java nécessitent le package java.util.regex.

Recherches

La classe Pattern offre la fonction matches qui renvoie un booléen : true (vrai) si la chaîne complète correspond à l'expression régulière, false (faux) sinon.

import java.util.regex.Pattern;

public class Regex
{
	public static void main(String[] args)
	{
		String chaine1 = "Test regex Java pour Wikibooks francophone.";
		System.out.println(Pattern.matches("[a-z]* Wikibooks",chaine1));
		System.out.println(Pattern.matches("[a-zA-Z ]* francophone\\.",chaine1));
	}
}
/*
	Affiche :
		false
		true
*/

La classe Matcher permet de trouver les résultats d'une expression avec différentes méthodes :

  1. find() : cherche le motif suivant et retourne un booléen indiquant si le motif défini par l'expression régulière a été trouvé.
  2. group() : retourne la chaîne trouvée (groupe 0).
  3. group(int) : retourne le groupe d'index spécifié. Le groupe 0 correspond à la chaîne complète, les suivants correspondent à la paire de parenthèses capturante dans l'expression régulière.
 pour échapper une chaine, utiliser Pattern.quote(ma_chaine); .

L'exemple ci-dessous affiche tous les mots en gras qu'il trouve dans l'extrait de texte au format HTML suivant :

Test <b>regex</b> <i>Java</i> pour <b>Wikibooks</b> francophone.
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class TestRegex
{
	public static void main(String[] args)
	{
		String chaine = "Test <b>regex</b> <i>Java</i> pour <b>Wikibooks</b> francophone.";
		Pattern p = Pattern.compile("<b>([^<]+)</b>"); // Capture du contenu entre <b> et </b> (groupe 1)
		Matcher m = p.matcher(chaine);
		while (m.find())
		{
			System.out.println(m.group());  // Tout le motif
			System.out.println(m.group(1)); // Le contenu entre <b> et </b>
		}
	}
}

Affiche :

<b>regex</b>
regex
<b>Wikibooks</b>
Wikibooks

Remplacements

On peut utiliser la méthode String.replaceAll(). Exemple pour les retirer les espaces : ma_chaine.replaceAll("\\s+", "").

Logo Par défaut elle ne remplace pas les caractères non-ASCII (ex "é"). Depuis Java 7 il vaut donc mieux utiliser Matcher.replaceAll().

Exemple avec Matcher :

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class Regex {
	public static void main(String[] args) {
		String chaine = "Test <b>regexé</b> <i>Java</i> pour <b>Wikibooks</b> francophone.";
		Pattern p = Pattern.compile("<b>([^<]+)</b>");
		Matcher m = p.matcher(chaine);
		System.out.println(m.replaceAll(""));
	}
}
/* Affiche :
Test  <i>Java</i> pour  francophone.
*/

Références

  1. https://unicode-table.com/fr/
  2. https://docstore.mik.ua/orelly/webprog/pcook/ch13_05.htm
  3. https://www.regular-expressions.info/posixbrackets.html
  4. http://www.regular-expressions.info/unicode.html
  5. https://www.regextester.com/15
  6. Jan Goyvaerts, Steven Levithan, Regular Expressions Cookbook, O'Reilly Media, Inc., (lire en ligne)
Cet article est issu de Wikibooks. Le texte est sous licence Creative Commons - Attribution - Partage dans les Mêmes. Des conditions supplémentaires peuvent s'appliquer aux fichiers multimédias.