Expressions régulières Java : Maîtriser la correspondance de motifs avec java.util.regex
Java fournit le package java.util.regex pour la correspondance de motifs avec les expressions régulières. Les expressions régulières Java sont très similaires à celles du langage Perl et faciles à apprendre.
Concepts fondamentaux
Une expression régulière est une séquence spéciale de caractères qui permet de rechercher, d'éditer ou de manipuler du texte et des données selon une syntaxe spécialisée contenue dans un motif.
Le package java.util.regex repose principalement sur trois classes :
- Pattern : Représentation compilée d'une expression régulière. Pas de constructeur public ; on utilise la méthode statique
compile()pour obtenir une instance. - Matcher : Moteur qui interprète le motif et effectue les opérations de correspondance sur une chaîne d'entrée. On l'obtient via
matcher()sur un objet Pattern. - PatternSyntaxException : Exception non vérifiée signalant une erreur de syntaxe dans le motif.
Groupes de capture
Les groupes de capture permettent de traiter plusieurs caractères comme une seule unité. Ils sont créés en plaçant les caractères entre parenthèses. Par exemple, (dog) crée un groupe unique contenant "d", "o", "g".
Les groupes sont numérotés en comptant les parenthèses ouvrantes de gauche à droite. Dans ((A)(B(C))), on trouve quatre groupes :
((A)(B(C)))(A)(B(C))(C)
La méthode groupCount() d'un Matcher retourne le nombre de groupes de capture. Le groupe 0 représente toujours l'expression entière et n'est pas inclus dans ce compte.
Exemple : extraction d'une chaîne numérique
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
public static void main(String args[]) {
String line = "This order was placed for QT3000! OK?";
String pattern = "(.*)(\\d+)(.*)";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(line);
if (m.find()) {
System.out.println("Valeur trouvée (groupe 0) : " + m.group(0));
System.out.println("Valeur trouvée (groupe 1) : " + m.group(1));
System.out.println("Valeur trouvée (groupe 2) : " + m.group(2));
} else {
System.out.println("AUCUNE CORRESPONDANCE");
}
}
}
Résultat :
Valeur trouvée (groupe 0) : This order was placed for QT3000! OK?
Valeur trouvée (groupe 1) : This order was placed for QT300
Valeur trouvée (groupe 2) : 0
Syntaxe des expressions régulières
Voici les méta-caractères principaux disponibles en Java :
| Sous-expression | Correspond à |
|---|---|
^ | Début de ligne |
$ | Fin de ligne |
. | Tout caractère sauf saut de ligne (option m pour inclure le saut de ligne) |
[...] | Tout caractère entre crochets |
[^...] | Tout caractère pas entre crochets |
\A | Début de la chaîne entière |
\z | Fin de la chaîne entière |
\Z | Fin de la chaîne (sauf terminaison de ligne finale autorisée) |
re* | 0 ou plusieurs occurrences de l'expression précédente |
re+ | 1 ou plusieurs occurrences |
re? | 0 ou 1 occurrence |
re{n} | Exactement n occurrences |
re{n,} | n occurrences ou plus |
re{n,m} | Entre n et m occurrences |
a|b | a ou b |
(re) | Groupe et mémorise le texte correspondant |
(?:re) | Groupe sans mémoriser (non-capturant) |
(?>re) | Motif indépendant sans backtracking |
\w | Caractères de mot [a-zA-Z0-9_] |
\W | Non-caractères de mot |
\s | Espace blanc [\t\n\r\f] |
\S | Non-espace blanc |
\d | Chiffres [0-9] |
\D | Non-chiffres |
\b | Frontière de mot (hors crochets) / retour arrière (dans crochets) |
\B | Non-frontière de mot |
\n, \t, etc. | Saut de ligne, tabulation, etc. |
\Q...\E | Échappe tous les caractères entre \Q et \E |
Méthodes principales de la classe Matcher
Méthodes d'index
| Méthode | Description |
|---|---|
start() | Index de début de la correspondance précédente |
start(int group) | Index de début du sous-groupe capturé |
end() | Offset après le dernier caractère correspondu |
end(int group) | Offset après le dernier caractère du sous-groupe |
Méthodes de recherche
| Méthode | Description |
|---|---|
lookingAt() | Tente une correspondance au début de la région |
find() | Trouve la prochaine sous-séquence correspondante |
find(int start) | Recherche à partir de l'index spécifié |
matches() | Tente une correspondance sur toute la région |
Méthodes de remplacement
| Méthode | Description |
|---|---|
appendReplacement(StringBuffer sb, String replacement) | Étape de remplacement non terminale |
appendTail(StringBuffer sb) | Étape de remplacement terminale |
replaceAll(String replacement) | Remplace toutes les occurrences |
replaceFirst(String replacement) | Remplace la première occurrence |
quoteReplacement(String s) | Retourne une chaîne de remplacement littérale |
Exemple : compter les occurrences du mot "chat"
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static final String REGEX = "\\bchat\\b";
private static final String INPUT = "chat chat chat chatterie chat";
public static void main(String args[]) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
int count = 0;
while (m.find()) {
count++;
System.out.println("Correspondance n°" + count);
System.out.println("start() : " + m.start());
System.out.println("end() : " + m.end());
}
}
}
Résultat :
Correspondance n°1 start(): 0 end(): 4
Correspondance n°2 start(): 5 end(): 9
Correspondance n°3 start(): 10 end(): 14
Correspondance n°4 start(): 21 end(): 25
L'utilisation de \b (frontière de mot) évite de correspondre à "chat" dans "chatterie".
Différence entre matches() et lookingAt()
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static final String REGEX = "foo";
private static final String INPUT = "fooooooooooooooooo";
public static void main(String args[]) {
Pattern pattern = Pattern.compile(REGEX);
Matcher matcher = pattern.matcher(INPUT);
System.out.println("REGEX actuel : " + REGEX);
System.out.println("INPUT actuel : " + INPUT);
System.out.println("lookingAt() : " + matcher.lookingAt()); // true
System.out.println("matches() : " + matcher.matches()); // false
}
}
Remplacement avec replaceFirst et replaceAll
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static String REGEX = "chien";
private static String INPUT = "Le chien dit miaou. Tous les chiens disent miaou.";
private static String REPLACE = "chat";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
INPUT = m.replaceAll(REPLACE);
System.out.println(INPUT);
}
}
Résultat : Le chat dit miaou. Tous les chats disent miaou.
appendReplacement et appendTail
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static String REGEX = "a*b";
private static String INPUT = "aabfooaabfooabfoob";
private static String REPLACE = "-";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, REPLACE);
}
m.appendTail(sb);
System.out.println(sb.toString());
}
}
Résultat : -foo-foo-foo-
Méthodes de PatternSyntaxException
| Méthode | Description |
|---|---|
getDescription() | Description de l'erreur |
getIndex() | Index de l'erreur |
getPattern() | Motif erroné |
getMessage() | Message multi-lignes détaillé |
Java
- Expressions, instructions et blocs C# : Guide complet avec exemples pratiques
- Maîtriser les opérateurs Java : Types, syntaxe et exemples pratiques
- Comprendre les expressions, instructions et blocs en Java
- Commentaires Java : Types, utilisation et bonnes pratiques
- Maîtriser la boucle for améliorée en Java : Syntaxe, exemples et bonnes pratiques
- Maîtriser les chaînes de caractères en Java : Création, méthodes et bonnes pratiques
- Maîtriser les interfaces Java : concepts, implémentation et bonnes pratiques
- Maîtriser le try-with-resources Java : gestion automatique des ressources expliquée
- Annotations Java expliquées : types, placement et exemples pratiques