Les indicateurs de regex Java
Modifiez le comportement des regex Java avec les indicateurs CASE_INSENSITIVE, MULTILINE, DOTALL, COMMENTS et la syntaxe inline (?i).
Un indicateur modifie l'interprétation d'une expression régulière sans toucher au motif lui-même. La même expression peut correspondre avec ou sans distinction de casse, traiter une chaîne comme une seule ligne ou plusieurs, et laisser . traverser les sauts de ligne ou s'arrêter à eux — tout cela est décidé par les indicateurs. En Java, on les définit de deux façons : sous forme de constantes int passées à Pattern.compile(pattern, flags), ou sous forme de modificateurs inline (?i) écrits à l'intérieur du motif. Ce chapitre couvre les indicateurs utilisés au quotidien et la façon de les combiner.
Les deux façons de définir un indicateur
Chaque indicateur possède une constante dans la classe Pattern. Passez-la en deuxième argument à compile :
Pattern p = Pattern.compile("error", Pattern.CASE_INSENSITIVE);Le même comportement est disponible à l'intérieur du motif sous forme de modificateur inline, ce qui permet à une expression régulière sous forme de chaîne brute de porter ses propres indicateurs sans second argument :
Pattern p = Pattern.compile("(?i)error"); // whole pattern, case-insensitive
Pattern q = Pattern.compile("(?i:error) CODE"); // only the group is case-insensitiveLes indicateurs inline sont pratiques lorsque le motif circule sous forme de chaîne brute — un fichier de configuration, une colonne de base de données, une annotation — là où il n'est pas possible de passer un int. La forme constante est plus lisible lorsque l'indicateur fait partie du code.
Les indicateurs que vous utiliserez vraiment
| Constante | Inline | Effet |
|---|---|---|
CASE_INSENSITIVE | (?i) | Correspondance des lettres ASCII sans distinction de casse |
MULTILINE | (?m) | ^ et $ correspondent à chaque limite de ligne, pas seulement aux extrémités de la chaîne |
DOTALL | (?s) | . correspond également aux terminateurs de ligne (s = "single line") |
COMMENTS | (?x) | Ignore les espaces non échappés et traite # comme un commentaire |
UNICODE_CASE | (?u) | Fait en sorte que CASE_INSENSITIVE traite les lettres Unicode, pas seulement ASCII |
UNICODE_CHARACTER_CLASS | (?U) | Fait en sorte que \w, \d, \b suivent les règles Unicode |
LITERAL | — | Traite le motif entier comme du texte brut, sans métacaractères |
Une surprise fréquente : CASE_INSENSITIVE seul ne plie que l'ASCII. Pour faire correspondre des lettres accentuées ou non latines sans distinction de casse, combinez-le avec UNICODE_CASE.
Insensibilité à la casse
Par défaut, une regex est sensible à la casse, donc error ne correspond pas à ERROR. Ajoutez CASE_INSENSITIVE et les deux correspondent :
Pattern.compile("error").matcher("ERROR").find(); // false
Pattern.compile("error", Pattern.CASE_INSENSITIVE).matcher("ERROR").find(); // true
// For non-ASCII letters, add UNICODE_CASE:
Pattern.compile("é", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE)
.matcher("É").find(); // trueGestion des lignes : MULTILINE et DOTALL
Ces deux indicateurs sont indépendants et souvent confondus. MULTILINE modifie les ancres ^ et $ ; DOTALL modifie le point ..
String text = "first line\nsecond line";
// Without MULTILINE, ^ matches only the very start of the input.
Pattern.compile("^second").matcher(text).find(); // false
// With MULTILINE, ^ matches the start of every line.
Pattern.compile("^second", Pattern.MULTILINE).matcher(text).find(); // true
// Without DOTALL, . will not cross the newline.
Pattern.compile("first.*second").matcher(text).find(); // false
// With DOTALL, . matches the newline too.
Pattern.compile("first.*second", Pattern.DOTALL).matcher(text).find(); // trueUtilisez MULTILINE pour analyser des journaux ou des textes multiligne ligne par ligne, et DOTALL lorsqu'une correspondance unique doit s'étendre sur plusieurs lignes (un bloc HTML, un enregistrement multiligne).
Combinaison des indicateurs
Les constantes d'indicateurs sont des masques de bits, donc vous les combinez avec l'opérateur OR bit à bit | :
int flags = Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
Pattern p = Pattern.compile("^error.*done$", flags);L'équivalent inline empile les lettres : (?ims) active les trois. Vous pouvez aussi désactiver un indicateur à l'intérieur d'un groupe avec un moins : (?-i) désactive l'insensibilité à la casse pour le reste du motif.
Motifs lisibles avec COMMENTS
L'indicateur COMMENTS (inline (?x)) permet à un motif complexe de respirer : les espaces non échappés sont ignorés et # commence un commentaire jusqu'à la fin de la ligne. Cela transforme une expression illisible en quelque chose que vous pouvez maintenir :
Pattern phone = Pattern.compile("""
\\d{3} # area code
- # separator
\\d{4} # line number
""", Pattern.COMMENTS);
phone.matcher("555-1234").matches(); // trueÉtant donné que les espaces réels sont ignorés, faites correspondre un espace littéral avec \\s, \\ , ou une classe de caractères comme [ ].
Un exemple complet : une expression, plusieurs indicateurs
Ce programme exécute le même ensemble de motifs avec et sans indicateurs pour que vous puissiez voir chaque indicateur changer le résultat. Il compte les correspondances sans distinction de casse, ancre les lignes avec MULTILINE, traverse les sauts de ligne avec DOTALL, combine les indicateurs avec |, et utilise à la fois les modificateurs inline globaux et délimités.
Ce que l'on retient de l'exécution :
CASE_INSENSITIVEa trouvé 2 occurrences deerror(leERRORen majuscules et leerroren minuscules) tandis que le motif par défaut n'en a trouvé qu'1 — preuve que la sensibilité à la casse est active sauf si vous demandez l'indicateur.MULTILINEa fait correspondre^error:.*$à la ligne du milieu du journal et affichéerror: timeout; sans l'indicateur,^et$n'ancreraient qu'aux extrémités de la chaîne entière, donc cette ligne intérieure ne correspondrait jamais.DOTALLa permis àwarn.*infode franchir les deux sauts de ligne intégrés et de correspondre (true), alors que le même motif sans l'indicateur renvoyaitfalsecar.s'arrête par défaut à un terminateur de ligne.- Le motif combiné
MULTILINE | CASE_INSENSITIVEa fait correspondre^ERRORà une ligne qui commence effectivement parerror:en minuscules —trueconfirme que les deux indicateurs ont été appliqués simultanément depuis un seul masque OR bit à bit. - Le
(?i:hello) WORLDdélimité a correspondu àHELLO WORLD(true) mais pas àHELLO world(false) : le groupe(?i:...)n'a plié la casse que pourhello, laissant leWORLDfinal strictement sensible à la casse — c'est précisément la précision que procure la délimitation inline.
Sujets connexes
- Expressions régulières Java — Introduction — comment
PatternetMatchers'articulent. - Pattern et Matcher — les classes qui utilisent les indicateurs ci-dessus.
- Syntaxe des regex et Classes de caractères — les métacaractères que les indicateurs modifient.
- Quantificateurs et Groupes — là où les modificateurs inline délimités comme
(?i:...)sont les plus utiles.