Nous présentons à votre attention une traduction d'un petit guide des expressions régulières en Java, rédigé par Jeff Friesen pour le site
javaworld . Pour faciliter la lecture, nous avons divisé l'article en plusieurs parties.
Expressions régulières en Java, partie 1
Fusionner plusieurs plages |
Vous pouvez fusionner plusieurs plages en une seule classe de caractères en les plaçant côte à côte. Par exemple, la classe [a-zA-Z] fait correspondre tous les caractères alphabétiques latins en minuscules ou en majuscules. |
Fusionner plusieurs plages
Vous pouvez fusionner plusieurs plages en une seule classe de caractères en les plaçant côte à côte. Par exemple, la classe
[a-zA-Z]
fait correspondre tous les caractères alphabétiques latins en minuscules ou en majuscules.
Combiner des classes de personnages
Une union de classes de caractères se compose de plusieurs classes de caractères imbriquées et correspond à tous les caractères de l'union résultante. Par exemple, la classe
[a-d[m-p]]
fait correspondre les caractères de
a
à
d
et de
m
à
p
. Prenons l'exemple suivant :
java RegexDemo [ab[c-e]] abcdef
Cet exemple recherchera les caractères
a
,
b
,
c
,
d
et
e
, pour lesquels il y a des correspondances dans
abcdef
:
regex = [ab[c-e]]
input = abcdef
Found [a] starting at 0 and ending at 0
Found [b] starting at 1 and ending at 1
Found [c] starting at 2 and ending at 2
Found [d] starting at 3 and ending at 3
Found [e] starting at 4 and ending at 4
Intersection des classes de caractères
L'intersection des classes de caractères est constituée de caractères communs à toutes les classes imbriquées et correspond uniquement aux caractères communs. Par exemple, la classe
[a-z&&[d-f]]
correspond aux caractères
d
,
e
et
f
. Prenons l'exemple suivant :
java RegexDemo "[aeiouy&&[y]]" party
Notez que sur mon système d'exploitation Windows, les guillemets doubles sont requis car le shell de commande les traite
&
comme un séparateur de commande. Cet exemple ne trouvera que le caractère
y
qui correspond à
party
:
regex = [aeiouy&&[y]]
input = party
Found [y] starting at 4 and ending at 4
Soustraire des classes de caractères
La soustraction des classes de caractères comprend tous les caractères à l'exception de ceux contenus dans les classes de caractères imbriquées et correspond uniquement aux caractères restants. Par exemple, la classe
[a-z&&[^m-p]]
recherche les caractères de
a
à
l
et de
q
à
z
:
java RegexDemo "[a-f&&[^a-c]&&[^e]]" abcdefg
Cet exemple trouvera les caractères
d
et
f
pour lesquels il y a des correspondances dans
abcdefg
:
regex = [a-f&&[^a-c]&&[^e]]
input = abcdefg
Found [d] starting at 3 and ending at 3
Found [f] starting at 5 and ending at 5
Classes de caractères prédéfinies
Certaines classes de caractères apparaissent assez fréquemment dans
les expressions régulières pour justifier l'utilisation d'une notation abrégée. La classe
Pattern
propose des classes de caractères prédéfinies telles que de telles abréviations. Vous pouvez les utiliser pour simplifier vos expressions régulières et minimiser les erreurs de syntaxe. Il existe plusieurs catégories de classes de caractères prédéfinies :
java.lang.Character
propriétés standard, POSIX et Unicode telles que script, bloc, catégorie et binaire. La liste suivante affiche uniquement la catégorie des classes standards :
\d
: Nombre. Équivalent [0-9]
.
\D
: Caractère non numérique. Équivalent [^0-9]
.
\s
: Caractère d'espacement. Équivalent [ \t\n\x0B\f\r]
.
\S
: Pas un caractère d'espacement. Équivalent [^\s]
.
\w
: Symbole formant un mot. Équivalent [a-zA-Z_0-9]
.
\W
: Pas un caractère formant un mot. Équivalent [^\w]
.
L'exemple suivant utilise une classe de caractères prédéfinie
\w
pour décrire tous les caractères de mot dans le texte d'entrée :
java RegexDemo \w "aZ.8 _"
Examinez attentivement les résultats d'exécution suivants, qui montrent que les points et les espaces ne sont pas considérés comme des caractères de mot :
regex = \w
input = aZ.8 _
Found [a] starting at 0 and ending at 0
Found [Z] starting at 1 and ending at 1
Found [8] starting at 3 and ending at 3
Found [_] starting at 5 and ending at 5
Séparateurs de lignes |
La documentation du SDK de classe Pattern décrit le métacaractère point comme une classe de caractères prédéfinie qui correspond à n'importe quel caractère à l'exception des séparateurs de ligne (séquences d'un ou deux caractères marquant la fin d'une ligne). L'exception est le mode dotall (dont nous parlerons ensuite), dans lequel les points correspondent également aux séparateurs de lignes. La classe Pattern distingue les séparateurs de lignes suivants :
- caractère de retour chariot (
\r );
- caractère de nouvelle ligne (symbole permettant d'avancer le papier d'une ligne) (
\n );
- un caractère de retour chariot immédiatement suivi d'un caractère de nouvelle ligne (
\r\n ) ;
- caractère de la ligne suivante (
\u0085 );
- caractère séparateur de ligne (
\u2028 );
- symbole de séparation de paragraphe (
\u2029 )
|
Groupes capturés
Le groupe de capture est utilisé pour enregistrer le jeu de caractères trouvé pour une utilisation ultérieure lors de la recherche par modèle. Cette construction est une séquence de caractères entourés de métacaractères par parenthèses (
( )
). Tous les personnages du groupe capturé sont considérés comme un tout lors de la recherche par modèle. Par exemple, le groupe de capture (
Java
) combine les lettres
J
,
a
et en une seule unité. Ce groupe de capture trouve toutes les occurrences du modèle dans le texte saisi. A chaque correspondance, les caractères stockés précédents sont remplacés par les suivants. Les groupes capturés peuvent être imbriqués dans d'autres groupes capturés. Par exemple, dans une expression régulière, un groupe est imbriqué dans un groupe . Chaque groupe de capture imbriqué ou non se voit attribuer un numéro, commençant à 1, et la numérotation va de gauche à droite. Dans l'exemple précédent, les correspondances capturent le numéro de groupe 1 et les correspondances capturent le numéro de groupe 2. Dans l'expression régulière , les correspondances capturent le numéro de groupe 1 et les correspondances capturent le numéro de groupe 2. Les correspondances stockées par les groupes de capture sont accessibles ultérieurement à l'aide de références arrière. Spécifiée sous la forme d'un caractère barre oblique inverse suivi d'un caractère numérique correspondant au numéro du groupe en cours de capture, la référence arrière permet de faire référence à des caractères du texte capturé par le groupe. Avoir un backlink amène le comparateur à se référer au résultat de recherche stocké du groupe capturé en fonction du numéro qu'il contient, puis à utiliser les caractères de ce résultat pour tenter une recherche plus approfondie. L'exemple suivant montre l'utilisation d'une référence arrière pour rechercher des erreurs grammaticales dans un texte : Cet exemple utilise une expression régulière pour rechercher une erreur grammaticale suivie immédiatement par un mot en double dans le texte saisi . Cette expression régulière spécifie deux groupes à capturer : le numéro 1 – , correspondant à et le numéro 2 – , correspondant au caractère espace suivi de . La référence arrière permet de revisiter le résultat stocké du groupe numéro 2 afin que le comparateur puisse rechercher la deuxième occurrence d'un espace suivi de , immédiatement après la première occurrence d'un espace et . Les résultats du matcheur sont les suivants :
v
a
Java
Java
(Java( language))
(language)
(Java)
(Java( language))
(language)
(a)(b)
(a)
(b)
java RegexDemo "(Java( language)\2)" "The Java language language"
(Java( language)\2)
language
Java
"The Java language language"
(Java( language)\2)
Java language language
(language)
language
\2
language
language
RegexDemo
regex = (Java( language)\2)
input = The Java language language
Found [Java language language] starting at 4 and ending at 25
Correspondants aux limites
Parfois, vous devez effectuer une correspondance de modèle au début d'une ligne, aux limites des mots, à la fin du texte, etc. Vous pouvez le faire en utilisant l'un des class Edge Matchers
Pattern
, qui sont des constructions d'expressions régulières qui recherchent des correspondances aux emplacements suivants :
^
: Début de ligne ;
$
: Fin de ligne;
\b
: Limite de mot ;
\B
: Limite du pseudo-mot ;
\A
: Début du texte ;
\G
: Fin du match précédent ;
\Z
: Fin du texte, sans compter le séparateur de ligne final (si présent) ;
\z
: Fin du texte
L'exemple suivant utilise le
^
métacaractère de correspondance de limites pour rechercher les lignes commençant par
The
, suivi de zéro ou plusieurs caractères de mot :
java RegexDemo "^The\w*" Therefore
Le caractère
^
spécifie que les trois premiers caractères du texte saisi doivent correspondre aux caractères de modèle consécutifs
T
,
h
et
e
, qui peuvent être suivis de n'importe quel nombre. de symboles formant des mots. Voici le résultat de l'exécution :
regex = ^The\w*
input = Therefore
Found [Therefore] starting at 0 and ending at 8
Que se passe-t-il si vous modifiez la ligne de commande en
java RegexDemo "^The\w*" " Therefore"
? Aucune correspondance ne sera trouvée car
Therefore
le texte saisi est précédé d'un caractère espace.
Correspondances de longueur nulle
Parfois, lorsque vous travaillez avec des Edge Matchers, vous rencontrerez des correspondances de longueur nulle.
Совпадение нулевой длины
est une correspondance qui ne contient aucun caractère. Ils peuvent apparaître dans un texte de saisie vide, au début du texte de saisie, après le dernier caractère du texte de saisie et entre deux caractères quelconques du texte de saisie. Les correspondances de longueur nulle sont faciles à reconnaître car elles commencent et se terminent toujours à la même position. Prenons l'exemple suivant :
java RegExDemo \b\b "Java is"
cet exemple recherche deux limites de mots consécutives et les résultats ressemblent à ceci :
regex = \b\b
input = Java is
Found [] starting at 0 and ending at -1
Found [] starting at 4 and ending at 3
Found [] starting at 5 and ending at 4
Found [] starting at 7 and ending at 6
Nous voyons plusieurs correspondances de longueur nulle dans les résultats. Les positions de fin ici sont une de moins que les positions de départ, puisque
RegexDemo
je l'ai spécifié dans le code source du listing 1
end() – 1
.
Quantificateurs
Un quantificateur est une construction d'expression régulière qui associe explicitement ou implicitement un modèle à une valeur numérique. Cette valeur numérique détermine combien de fois rechercher le modèle. Les quantificateurs sont divisés en gourmands, paresseux et super gourmands :
- Le quantificateur glouton (
?
, *
ou +
) est conçu pour trouver la correspondance la plus longue. Puis-je demander X
? pour trouver une ou moins d'occurrences X
, X*
pour trouver zéro ou plusieurs occurrences X
, X+
pour trouver une ou plusieurs occurrences X
, X{n}
pour trouver n
des occurrences X
, X{n,}
pour trouver au moins (et éventuellement plus) n
d'occurrences , X
et X{n,m}
pour trouver au moins n
mais pas plus m
d'occurrences X
.
- Le quantificateur paresseux (
??
, *?
ou +?
) est conçu pour trouver la correspondance la plus courte. Vous pouvez spécifier X??
de rechercher une ou plusieurs occurrences de X
,X*
? pour trouver zéro ou plusieurs occurrences X
, X+?
pour trouver une ou plusieurs occurrences X
, X{n}?
pour trouver n
des occurrences X
, X{n,}?
pour trouver au moins (et éventuellement plus) n
d'occurrences X
, et X{n,m}?
pour trouver au moins n
mais pas plus m
d'occurrences X
.
- Le quantificateur super-gourmand (
?+
, *+
ou ++
) est similaire au quantificateur glouton, sauf que le quantificateur super-gourmand ne fait qu'une seule tentative pour trouver la correspondance la plus longue, tandis que le quantificateur glouton peut faire plusieurs tentatives. Peut être configuré X?+
pour rechercher une ou moins d'occurrences X
, X*+
pour rechercher zéro ou plusieurs occurrences X
, X++
pour rechercher une ou plusieurs occurrences X
, X{n}+
pour rechercher n
des occurrences de X
, X{n,}+
pour trouver au moins (et éventuellement plus) n
d'occurrences X
et X{n,m}+
pour trouver au moins n
mais pas plus d' m
occurrences . X
.
L'exemple suivant illustre l'utilisation du quantificateur glouton :
java RegexDemo .*ox "fox box pox"
Voici les résultats :
regex = .*ox
input = fox box pox
Found [fox box pox] starting at 0 and ending at 10
Le quantificateur glouton (
.*
) trouve la plus longue séquence de caractères se terminant par
ox
. Il consomme l'intégralité du texte saisi, puis revient en arrière jusqu'à ce qu'il détecte que le texte saisi se termine par ces caractères. Considérons maintenant le quantificateur paresseux :
java RegexDemo .*?ox "fox box pox"
ses résultats :
regex = .*?ox
input = fox box pox
Found [fox] starting at 0 and ending at 2
Found [ box] starting at 3 and ending at 6
Found [ pox] starting at 7 and ending at 10
Le quantificateur paresseux (
.*?
) trouve la séquence la plus courte de caractères se terminant par
ox
. Il commence par une chaîne vide et consomme progressivement des caractères jusqu'à ce qu'il trouve une correspondance. Et continue ensuite à travailler jusqu'à ce que le texte saisi soit épuisé. Enfin, regardons le quantificateur super-gourmand :
java RegexDemo .*+ox "fox box pox"
Et voici ses résultats :
regex = .*+ox
input = fox box pox
Le quantificateur extra-gourmand (
.*+
) ne trouve pas de correspondance car il consomme tout le texte saisi et il ne reste plus rien à trouver
ox
à la fin de l'expression régulière. Contrairement au quantificateur glouton, le quantificateur super gourmand ne revient pas en arrière.
Correspondances de longueur nulle
Parfois, lorsque vous travaillez avec des quantificateurs, vous rencontrerez des correspondances de longueur nulle. Par exemple, l'utilisation du quantificateur glouton suivant entraîne plusieurs correspondances de longueur nulle :
java RegexDemo a? abaa
Les résultats de l'exécution de cet exemple :
regex = a?
input = abaa
Found [a] starting at 0 and ending at 0
Found [] starting at 1 and ending at 0
Found [a] starting at 2 and ending at 2
Found [a] starting at 3 and ending at 3
Found [] starting at 4 and ending at 3
Il y a cinq correspondances dans les résultats d'exécution. Bien que les premier, troisième et quatrième soient assez attendus (ils correspondent aux positions de trois lettres
a
dans
abaa
), le deuxième et le cinquième risquent de vous surprendre. Il semble qu’ils indiquent ce qui
a
correspond
b
à la fin du texte, mais en réalité ce n’est pas le cas. L'expression régulière
a?
ne recherche pas
b
à la fin du texte. Il recherche la présence ou l'absence
a
. Lorsqu'il
a?
ne trouve pas
a
, il le signale comme une correspondance de longueur nulle.
Expressions de drapeau imbriquées
Les matchers font des hypothèses par défaut qui peuvent être remplacées lors de la compilation de l'expression régulière dans un modèle. Nous discuterons de cette question plus tard. Une expression régulière vous permet de remplacer n'importe quelle valeur par défaut à l'aide d'une expression d'indicateur imbriquée. Cette construction d'expression régulière est spécifiée sous la forme d'un métacaractère composé de parenthèses autour d'un métacaractère de point d'interrogation (
?
), suivi d'une lettre latine minuscule. La classe
Pattern
comprend les expressions d'indicateur imbriquées suivantes :
(?i)
: Active la correspondance de modèle insensible à la casse. Par exemple, lors de l'utilisation d'une commande, java RegexDemo (?i)tree Treehouse
la séquence de caractères Tree
correspond au modèle tree
. La valeur par défaut est la recherche de modèles sensibles à la casse.
(?x)
: Permet l'utilisation de caractères d'espacement et de commentaires commençant par le métacaractère dans le modèle #
. Le matcher ignorera les deux. Par exemple, pour java RegexDemo ".at(?x)#match hat, cat, and so on" matter
une séquence de caractères mat
correspond au modèle .at
. Par défaut, les espaces et les commentaires ne sont pas autorisés et le comparateur les traite comme des caractères impliqués dans la recherche.
(?s)
: Active le mode dotall, dans lequel le métacaractère point correspond aux séparateurs de ligne en plus de tout autre caractère. Par exemple, la commande java RegexDemo (?s). \n
trouvera un caractère de nouvelle ligne. La valeur par défaut est l'opposé de dotall : aucun séparateur de ligne ne sera trouvé. Par exemple, la commande Java RegexDemo . \n
ne trouvera pas de caractère de nouvelle ligne.
(?m)
: Active le mode multiligne, où il ^
fait correspondre le début et $
la fin de chaque ligne. Par exemple, java RegexDemo "(?m)^abc$" abc\nabc
recherche les deux séquences dans le texte saisi abc
. Par défaut, le mode sur une seule ligne est utilisé : ^
correspond au début de l'intégralité du texte saisi et $
correspond à la fin de celui-ci. Par exemple, java RegexDemo "^abc$" abc\nabc
renvoie une réponse indiquant qu'il n'y a aucune correspondance.
(?u)
: Active l'alignement de la casse sensible à Unicode. Cet indicateur, lorsqu'il est utilisé conjointement avec (?i)
, permet une correspondance de modèle insensible à la casse conformément à la norme Unicode. Le paramètre par défaut consiste à rechercher uniquement les caractères sensibles à la casse et US-ASCII.
(?d)
: Active le mode chaîne de style Unix, où le comparateur reconnaît les métacaractères dans le contexte .
, ^
et $
uniquement le séparateur de ligne \n
. La valeur par défaut est le mode chaîne de style non Unix : le matcher reconnaît, dans le contexte des métacaractères ci-dessus, tous les délimiteurs de ligne.
Les expressions de drapeau imbriquées ressemblent à des groupes capturés car leurs caractères sont entourés de métacaractères entre parenthèses. Contrairement aux groupes capturés, les expressions d'indicateur imbriquées sont un exemple de groupes non capturés, qui sont une construction d'expression régulière qui ne capture pas les caractères de texte. Ils sont définis comme des séquences de caractères entourées de métacaractères de parenthèses.
Spécification de plusieurs expressions d'indicateur imbriquées |
Il est possible de spécifier plusieurs expressions de drapeau imbriquées dans une expression régulière en les plaçant côte à côte ( (?m)(?i)) ) ou en plaçant les lettres qui les définissent séquentiellement ( (?mi) ). |
Conclusion
Comme vous l'avez probablement déjà réalisé, les expressions régulières sont extrêmement utiles et le deviennent encore plus à mesure que vous maîtrisez les nuances de leur syntaxe. Jusqu'à présent, je vous ai présenté les bases des expressions régulières et du
Pattern
. Dans la deuxième partie, nous examinerons plus en détail l'API Regex et explorerons les méthodes de
Pattern
,
Matcher
et
PatternSyntaxException
. Je vais également vous montrer deux applications pratiques de l'API Regex que vous pouvez utiliser immédiatement dans vos programmes.
Expressions régulières en Java, partie 3 Expressions régulières en Java, partie 4 Expressions régulières en Java, partie 5
GO TO FULL VERSION