W3docs

Syntaxe des expressions régulières Java

Syntaxe des expressions régulières Java : caractères, classes, ancres, quantificateurs et constructions spéciales.

Une expression régulière est un mini-langage de modèles pour décrire du texte. Java l'implémente dans le package java.util.regex, et la syntaxe est le dialecte style Perl partagé par la plupart des langages modernes — avec une particularité propre à Java : chaque barre oblique inverse dans un motif doit être doublée dans un littéral de chaîne Java, car le compilateur en consomme une avant que le moteur regex ne la voie. Ce chapitre est une référence à cette syntaxe : les éléments de base que vous combinez pour rechercher, trouver et valider du texte.

Si vous débutez avec les expressions régulières en Java, commencez par l'Introduction aux Regex Java, puis revenez ici quand vous avez besoin du mémo complet de la syntaxe.

Littéraux et métacaractères

La plupart des caractères dans un motif se correspondent eux-mêmes : cat correspond aux trois lettres c, a, t. La puissance vient des métacaractères — des caractères ayant une signification spéciale que vous combinez en règles. Les douze que le moteur traite de façon particulière sont :

. ^ $ * + ? ( ) [ ] { } | \

Pour faire correspondre l'un d'eux littéralement, échappez-le avec une barre oblique inverse. N'oubliez pas la règle du double-backslash pour les sources Java : un regex \. s'écrit "\\." dans le code.

Pattern.matches("a.c", "abc");   // true  — '.' matches any char
Pattern.matches("a.c", "a.c");   // true  — '.' also matches a literal dot
Pattern.matches("a\\.c", "abc"); // false — '\.' matches ONLY a literal dot
Pattern.matches("a\\.c", "a.c"); // true

Classes de caractères

Une classe de caractères entre crochets correspond à n'importe quel unique caractère d'un ensemble. Les plages utilisent un tiret, et un ^ en tête annule l'ensemble.

"[aeiou]"     // any one lowercase vowel
"[a-z]"       // any one lowercase letter
"[A-Za-z0-9]" // any letter or digit
"[^0-9]"      // any character that is NOT a digit

Java propose également des classes prédéfinies comme raccourcis. Voici celles que vous utilisez constamment :

RaccourciÉquivalentCorrespond à
.Tout caractère sauf un terminateur de ligne
\d[0-9]Un chiffre
\D[^0-9]Un non-chiffre
\w[a-zA-Z0-9_]Un caractère de mot
\W[^a-zA-Z0-9_]Un caractère non-mot
\s[ \t\n\x0B\f\r]Un caractère d'espacement
\S[^\s]Un caractère non-espace

La forme majuscule est toujours la négation de la forme minuscule. Consultez Classes de caractères Regex Java pour l'ensemble complet, y compris les classes POSIX et Unicode.

Quantificateurs : gourmands, réticents, possessifs

Un quantificateur indique combien de fois l'élément précédent peut se répéter. Par défaut, les quantificateurs sont gourmands — ils prennent autant que possible, puis reculent si le reste du motif l'exige. Ajoutez ? pour rendre un quantificateur réticent (correspondre aussi peu que possible), ou + pour le rendre possessif (prendre sans jamais lâcher).

QuantificateurSignification
*Zéro ou plusieurs
+Un ou plusieurs
?Zéro ou un (optionnel)
{n}Exactement n
{n,}Au moins n
{n,m}Entre n et m
"\\d{3}"     // exactly three digits
"\\d{2,4}"   // two to four digits
"a+"         // one or more 'a'
"colou?r"    // matches "color" and "colour"
"<.+>"       // greedy:    on "<a><b>" matches the whole "<a><b>"
"<.+?>"      // reluctant: on "<a><b>" matches just "<a>"

Pour une étude approfondie du comportement gourmand, réticent et possessif, consultez Quantificateurs Regex Java.

Ancres, frontières et alternance

Les ancres correspondent à une position, pas à un caractère. ^ est le début de l'entrée (ou de la ligne, en mode multiligne), $ est la fin, et \b est une frontière de mot — la position de largeur nulle entre un \w et un \W. L'alternance avec | correspond à l'un ou l'autre côté.

"^Hello"      // "Hello" only at the start
"\\.txt$"     // ".txt" only at the end
"\\bcat\\b"   // "cat" as a whole word, not inside "category"
"cat|dog"     // "cat" or "dog"
"^(cat|dog)$" // the whole string is exactly "cat" or "dog"

Notez que | a une très faible priorité : ^cat|dog$ signifie (^cat)|(dog$), et non ^(cat|dog)$. Enveloppez les alternatives dans un groupe quand vous souhaitez que les ancres s'appliquent aux deux.

Groupes, rétro-références et indicateurs en ligne

Les parenthèses créent un groupe capturant — le moteur mémorise ce que chaque groupe a capturé, numérotés de gauche à droite à partir de 1. (?:...) est un groupe non-capturant quand vous avez seulement besoin d'appliquer un quantificateur. Une rétro-référence \1 correspond au même texte que celui capturé par le premier groupe. Les indicateurs en ligne comme (?i) modifient le comportement de correspondance sans paramètre séparé de Pattern.compile.

"(\\d{4})-(\\d{2})"   // group 1 = year, group 2 = month
"(?:ab)+"             // repeats "ab" without capturing it
"(\\w+) \\1"          // a word followed by itself ("the the")
"(?i)java"            // case-insensitive: matches "Java", "JAVA"
"(?m)^line"           // multiline: ^ matches at each line start

Les groupes capturants ont leur propre chapitre — Groupes Regex Java couvre les groupes nommés et comment extraire le texte capturé d'un Matcher. Les indicateurs en ligne comme (?i) et (?m) sont les équivalents intégrés dans le motif des indicateurs de Pattern.compile décrits dans Indicateurs Regex Java.

Un exemple concret : les constructions en action

Ce programme illustre une classe de chiffres avec un quantificateur, une alternance ancrée, une rétro-référence, la correspondance gourmande versus réticente, le raccourci \w+, et un indicateur insensible à la casse en ligne — tout en utilisant uniquement java.util.regex. La syntaxe ici pilote l'API Pattern et Matcher couverte dans Pattern et Matcher Regex Java.

java— editable, runs on the server

Ce qu'il faut retenir de l'exécution :

  • \d{4} a trouvé à la fois 1995 et 2011 car find() recherche chaque occurrence dans l'entrée, tandis qu'une classe associée à un quantificateur (\d répété {4} fois) est la façon canonique de correspondre à un champ de largeur fixe. Le double backslash dans "\\d{4}" est le littéral de chaîne Java qui produit le backslash simple que le moteur attend.
  • Pattern.matches("cat|dog", "dog") a retourné true mais le même motif sur "catnap" a retourné falsematches() ancre implicitement la totalité de l'entrée, donc même si cat apparaît dans catnap, le nap restant n'est pas capturé et la correspondance globale échoue.
  • La rétro-référence \1 a transformé (\w+) \1 en "un mot suivi du mot identique", c'est pourquoi elle a signalé the et is — les deux répétitions — et ignoré chaque mot qui n'était pas immédiatement répété. Les rétro-références correspondent au texte capturé, pas au motif à nouveau.
  • Sur la même entrée <a><b>, le gourmand <.+> a avalé toute la chaîne tandis que le réticent <.+?> s'est arrêté au premier >, ne donnant que <a>. Ce contraste unique est la correction de bug regex la plus fréquente que vous ferez jamais : ajoutez ? à un quantificateur quand il prend trop.
  • \w+ a compté 3 jetons dans ab, cd-ef!ab, cd et ef — car ,, - et ! sont tous des \W (caractères non-mot) qui brisent une séquence de caractères de mot. L'indicateur (?i) en ligne a ensuite fait correspondre java à JAVA, montrant que les indicateurs peuvent résider à l'intérieur du motif lui-même plutôt que seulement dans Pattern.compile.

Exercice

Pratique
Sur l'entrée '<a><b>', pourquoi le regex '<.+>' correspond-il à toute la chaîne '<a><b>' tandis que '<.+?>' ne correspond qu'à '<a>' ?
Sur l'entrée '<a><b>', pourquoi le regex '<.+>' correspond-il à toute la chaîne '<a><b>' tandis que '<.+?>' ne correspond qu'à '<a>' ?
Was this page helpful?