JavaRush /Blog Java /Random-FR /Expressions régulières en Java (RegEx)

Expressions régulières en Java (RegEx)

Publié dans le groupe Random-FR
Les expressions régulières sont un sujet que les programmeurs, même expérimentés, remettent souvent à plus tard. Cependant, la plupart des développeurs Java seront tôt ou tard confrontés au traitement de texte. Le plus souvent - avec des opérations de recherche dans le texte et d'édition. Sans expressions régulières, un code de programme productif et compact associé au traitement de texte est tout simplement impensable. Alors arrêtez de remettre à plus tard, parlons des « habitués » dès maintenant. Ce n’est pas une tâche si difficile.

Qu’est-ce que l’expression régulière RegEx ?

En fait, une expression régulière (RegEx en Java) est un modèle permettant de rechercher une chaîne dans un texte. En Java, la représentation initiale de ce modèle est toujours une chaîne, c'est-à-dire un objet de la classe String. Cependant, aucune chaîne ne peut être compilée dans une expression régulière, seules celles qui suivent les règles d'écriture d'une expression régulière - la syntaxe définie dans la spécification du langage. Pour écrire une expression régulière, des caractères alphabétiques et numériques sont utilisés, ainsi que des métacaractères - des caractères qui ont une signification particulière dans la syntaxe des expressions régulières. Par exemple:
String regex = "java"; // string template "java";
String regex = "\\d{3}"; // string template of three numeric characters;

Création d'expressions régulières en Java

Pour créer un RegEx en Java, vous devez suivre deux étapes simples :
  1. écrivez-le sous forme de chaîne en utilisant la syntaxe d'expression régulière ;
  2. compilez cette chaîne dans une expression régulière ;
Travailler avec des expressions régulières dans n'importe quel programme Java commence par la création d'un objet de classe Pattern. Pour ce faire, vous devez appeler l'une des deux méthodes statiques disponibles dans la classe compile. La première méthode prend un argument - une chaîne littérale d'une expression régulière, et la seconde - plus un autre paramètre qui active le mode de comparaison du modèle avec du texte :
public static Pattern compile (String literal)
public static Pattern compile (String literal, int flags)
La liste des valeurs de paramètres possibles flagsest définie dans la classe Patternet est à notre disposition sous forme de variables de classe statiques. Par exemple:
Pattern pattern = Pattern.compile("java", Pattern.CASE_INSENSITIVE);//searching for matches with the pattern will be done case-insensitively.
Essentiellement, la classe Patternest un constructeur d’expressions régulières. Sous le capot, la méthode compileappelle le constructeur privé de la classe Patternpour créer une vue compilée. Cette méthode de création d'une instance de modèle est implémentée dans le but de la créer en tant qu'objet immuable. Lors de la création, une vérification syntaxique de l'expression régulière est effectuée. S'il y a des erreurs dans la ligne, une exception est générée PatternSyntaxException.

Syntaxe des expressions régulières

La syntaxe des expressions régulières est basée sur l'utilisation de symboles <([{\^-=$!|]})?*+.>, qui peuvent être combinés avec des caractères alphabétiques. Selon leur rôle, ils peuvent être divisés en plusieurs groupes :
1. Métacaractères pour faire correspondre les limites de ligne ou le texte
Métacaractère But
^ début de ligne
$ fin de ligne
\b limite de mot
\B pas une limite de mots
\UN début de la saisie
\G fin du match précédent
\Z fin de la saisie
\z fin de la saisie
2. Métacaractères pour rechercher des classes de personnages
Métacaractère But
\d symbole numérique
\D caractère non numérique
\s caractère spatial
\S caractère autre qu'un espace
\w caractère alphanumérique ou trait de soulignement
\W tout caractère autre qu'un caractère alphabétique, numérique ou un trait de soulignement
. N'importe quel caractère
3. Métacaractères pour rechercher des symboles d'édition de texte
Métacaractère But
\t caractère de tabulation
\n caractère de nouvelle ligne
\r caractère de retour chariot
\F aller à une nouvelle page
\u0085 caractère de la ligne suivante
\u2028 caractère séparateur de ligne
\u2029 symbole de séparateur de paragraphe
4. Métacaractères pour regrouper les personnages
Métacaractère But
[aBC] l'un des éléments ci-dessus (a, b ou c)
[^abc] tout autre que ceux énumérés (pas a, b, c)
[a-zA-Z] fusion de plages (les caractères latins a à z ne sont pas sensibles à la casse)
[annonce[mp]] concaténation de caractères (a à d et m à p)
[az&&[déf]] intersection de symboles (symboles d,e,f)
[az&&[^bc]] soustraire des caractères (caractères a, dz)
5. Métasymboles pour indiquer le nombre de caractères - quantificateurs. Le quantificateur vient toujours après un caractère ou un groupe de caractères.
Métacaractère But
? un ou manquant
* zéro ou plusieurs fois
+ une ou plusieurs fois
{n} n fois
{n,} n fois ou plus
{n,m} pas moins de n fois et pas plus de m fois

Mode quantificateur gourmand

Une particularité des quantificateurs est la possibilité de les utiliser dans différents modes : gourmand, super gourmand et paresseux. Le mode extra-gourmand est activé en ajoutant le symbole «+ » après le quantificateur, et le mode paresseux en ajoutant le symbole «? ». Par exemple:
"A.+a" // greedy mode
"A.++a" // over-greedy mode
"A.+?a" // lazy mode
En utilisant ce modèle comme exemple, essayons de comprendre comment les quantificateurs fonctionnent dans différents modes. Par défaut, le quantificateur fonctionne en mode gourmand. Cela signifie qu'il recherche la correspondance la plus longue possible dans la chaîne. Suite à l'exécution de ce code :
public static void main(String[] args) {
    String text = "Egor Alla Alexander";
    Pattern pattern = Pattern.compile("A.+a");
    Matcher matcher = pattern.matcher(text);
    while (matcher.find()) {
        System.out.println(text.substring(matcher.start(), matcher.end()));
    }
}
nous obtiendrons le résultat suivant : Alla Alexa L'algorithme de recherche pour un modèle donné " А.+а" est effectué dans l'ordre suivant :
  1. Dans le modèle donné, le premier caractère est la lettre russe А. Matcherle compare à chaque caractère du texte, en commençant à la position zéro. À la position zéro dans notre texte, il y a un symbole Е, il parcourt donc Matcherles caractères du texte séquentiellement jusqu'à ce qu'il corresponde au modèle. Dans notre exemple, il s'agit du symbole en position n°5.

    Expressions régulières en Java - 2
  2. Une fois qu'une correspondance est trouvée avec le premier caractère du modèle, Matcheril vérifie la correspondance avec le deuxième caractère du modèle. Dans notre cas, il s'agit du symbole «. », qui représente n'importe quel caractère.

    Expressions régulières en Java - 3

    En sixième position se trouve le symbole de la lettre л. Bien sûr, cela correspond au modèle « n’importe quel caractère ».

  3. Matcherpasse ensuite à la vérification du caractère suivant du modèle. Dans notre modèle, il est spécifié à l'aide du .+quantificateur « ». Étant donné que le nombre de répétitions de « n'importe quel caractère » dans le modèle est une ou plusieurs fois, Matcheril prend tour à tour le caractère suivant de la chaîne et vérifie sa conformité avec le modèle, tant que la condition « n'importe quel caractère » est remplie, dans notre exemple - jusqu'à la fin de la ligne ( de la position n°7 - n°18 du texte).

    Expressions régulières en Java - 4

    En fait, Matcheril capture toute la ligne jusqu'au bout - c'est là que sa « cupidité » se manifeste.

  4. Après Matcheravoir atteint la fin du texte et fini de vérifier la А.+partie « » du motif, Matcher commence à vérifier le reste du motif - le caractère de la lettre а. Le texte dans le sens avant étant terminé, la vérification s'effectue dans le sens inverse, à partir du dernier caractère :

    Expressions régulières en Java - 5
  5. Matcher"se souvient" du nombre de répétitions dans le modèle " .+" auquel il a atteint la fin du texte, il réduit donc le nombre de répétitions d'une et vérifie le modèle du texte jusqu'à ce qu'une correspondance soit trouvée : Expressions régulières en Java - 6

Mode quantificateur ultra gourmand

En mode super gourmand, le matcher fonctionne de la même manière que le mécanisme du mode gourmand. La différence est que lorsque vous récupérez le texte jusqu’à la fin de la ligne, il n’y a pas de recherche en arrière. Autrement dit, les trois premières étapes du mode super gourmand seront similaires au mode gourmand. Après avoir capturé la chaîne entière, le comparateur ajoute le reste du motif et le compare avec la chaîne capturée. Dans notre exemple, lors de l'exécution de la méthode main avec le modèle " А.++а", aucune correspondance ne sera trouvée. Expressions régulières en Java - 7

Mode quantificateur paresseux

  1. Dans ce mode, au stade initial, comme dans le mode gourmand, une correspondance est recherchée avec le premier caractère du motif :

    Expressions régulières en Java - 8
  2. Ensuite, il recherche une correspondance avec le caractère suivant du modèle - n'importe quel caractère :

    Expressions régulières en Java - 9
  3. Contrairement au mode gourmand, le mode paresseux recherche la correspondance la plus courte dans le texte, donc après avoir trouvé une correspondance avec le deuxième caractère du motif, qui est spécifié par un point et correspond au caractère à la position n°6 du texte, il Matchervérifiera si le texte correspond au reste du motif - le caractère «а » .

    Expressions régulières en Java - 10
  4. Puisqu'aucune correspondance avec le motif dans le texte n'a été trouvée (à la position n° 7 dans le texte il y a le symbole " " л), Matcheril ajoute un autre "n'importe quel caractère" dans le motif, puisqu'il est spécifié comme une ou plusieurs fois, et compare à nouveau le motif avec le texte aux positions n° 5 à n° 8 :

    Expressions régulières en Java - 11
  5. Dans notre cas, une correspondance a été trouvée, mais la fin du texte n'est pas encore atteinte. Ainsi, à partir de la position n°9, la vérification commence par la recherche du premier caractère du motif à l'aide d'un algorithme similaire puis se répète jusqu'à la fin du texte.

    Expressions régulières en Java - 12
Grâce à la méthode, mainen utilisant le А.+?аmodèle " ", nous obtiendrons le résultat suivant : Alla Alexa Comme le montre notre exemple, en utilisant différents modes de quantificateur pour le même modèle, nous obtenons des résultats différents. Il faut donc prendre en compte cette fonctionnalité et sélectionner le mode souhaité en fonction du résultat souhaité lors de la recherche.

Échapper des caractères dans les expressions régulières

Puisqu'une expression régulière en Java, ou plus précisément sa représentation initiale, est spécifiée à l'aide d'une chaîne littérale, il est nécessaire de prendre en compte les règles de la spécification Java relatives aux chaînes littérales. En particulier, la barre oblique inverse " \" dans les chaînes littérales du code source Java est interprétée comme un caractère d'échappement qui avertit le compilateur que le caractère qui le suit est un caractère spécial et doit être interprété d'une manière particulière. Par exemple:
String s = "The root directory is \nWindows";//wrap Windows to a new line
String s = "The root directory is \u00A7Windows";//insert paragraph character before Windows
Par conséquent, dans les chaînes littérales qui décrivent une expression régulière et utilisent le \caractère « » (par exemple, pour les métacaractères), il doit être doublé afin que le compilateur de bytecode Java ne l'interprète pas différemment. Par exemple:
String regex = "\\s"; // template for searching for space characters
String regex = "\"Windows\""; // pattern to search for the string "Windows"
Le caractère double barre oblique inverse doit également être utilisé pour échapper aux caractères spéciaux si nous envisageons de les utiliser comme caractères « normaux ». Par exemple:
String regex = "How\\?"; // template for searching the string "How?"

Méthodes de la classe Pattern

La classe Patterndispose d'autres méthodes pour travailler avec des expressions régulières : String pattern()– renvoie la représentation sous forme de chaîne d'origine de l'expression régulière à partir de laquelle l'objet a été créé Pattern:
Pattern pattern = Pattern.compile("abc");
System.out.println(Pattern.pattern())//"abc"
static boolean matches(String regex, CharSequence input)– vous permet de vérifier l'expression régulière passée dans le paramètre regex par rapport au texte passé dans le paramètre input. Renvoie : true – si le texte correspond au modèle ; faux – sinon ; Exemple:
System.out.println(Pattern.matches("A.+a","Alla"));//true
System.out.println(Pattern.matches("A.+a","Egor Alla Alexander"));//false
int flags()– renvoie les flagsvaleurs des paramètres du modèle qui ont été définies lors de sa création, ou 0 si ce paramètre n'a pas été défini. Exemple:
Pattern pattern = Pattern.compile("abc");
System.out.println(pattern.flags());// 0
Pattern pattern = Pattern.compile("abc",Pattern.CASE_INSENSITIVE);
System.out.println(pattern.flags());// 2
String[] split(CharSequence text, int limit)– divise le texte passé en paramètre en un tableau d'éléments String. Le paramètre limitdétermine le nombre maximum de correspondances recherchées dans le texte :
  • quand limit>0– la recherche de limit-1correspondances est effectuée ;
  • at limit<0– recherche toutes les correspondances dans le texte
  • when limit=0– recherche toutes les correspondances dans le texte, tandis que les lignes vides à la fin du tableau sont ignorées ;
Exemple:
public static void main(String[] args) {
    String text = "Egor Alla Anna";
    Pattern pattern = Pattern.compile("\\s");
    String[] strings = pattern.split(text,2);
    for (String s : strings) {
        System.out.println(s);
    }
    System.out.println("---------");
    String[] strings1 = pattern.split(text);
    for (String s : strings1) {
        System.out.println(s);
    }
}
Sortie de la console : Egor Alla Anna -------- Egor Alla Anna Nous considérerons ci-dessous une autre méthode de classe pour créer un objet Matcher.

Méthodes de classe Matcher

Matcherest une classe à partir de laquelle un objet est créé pour rechercher des modèles. Matcher– il s’agit d’un « moteur de recherche », d’un « moteur » d’expressions régulières. Pour effectuer une recherche, il doit disposer de deux choses : un modèle de recherche et une « adresse » à rechercher. Pour créer un objet, Matcherla méthode suivante est fournie dans la classe Pattern: рublic Matcher matcher(CharSequence input) En argument, la méthode prend une séquence de caractères dans laquelle la recherche sera effectuée. Ce sont des objets de classes qui implémentent l'interface CharSequence. Vous pouvez passer non seulement String, mais aussi StringBuffer, StringBuilderet comme argument . Le modèle de recherche est l'objet de classe sur lequel la méthode est appelée . Exemple de création d'un matcher : SegmentCharBufferPatternmatcher
Pattern p = Pattern.compile("a*b");// compiled the regular expression into a view
Matcher m = p.matcher("aaaaab");//created a search engine in the text “aaaaab” using the pattern "a*b"
Désormais, avec l'aide de notre « moteur de recherche », nous pouvons rechercher des correspondances, connaître la position de la correspondance dans le texte et remplacer le texte à l'aide de méthodes de classe. La méthode boolean find()recherche la correspondance suivante dans le texte avec le modèle. Grâce à cette méthode et à l'opérateur de boucle, vous pouvez analyser l'intégralité du texte selon le modèle d'événement (effectuer les opérations nécessaires lorsqu'un événement se produit - trouver une correspondance dans le texte). Par exemple, en utilisant les méthodes de cette classe, int start()vous int end()pouvez déterminer les positions des correspondances dans le texte et, en utilisant les méthodes String replaceFirst(String replacement), String replaceAll(String replacement)remplacer les correspondances dans le texte par un autre texte de remplacement. Exemple:
public static void main(String[] args) {
    String text = "Egor Alla Anna";
    Pattern pattern = Pattern.compile("A.+?a");

    Matcher matcher = pattern.matcher(text);
    while (matcher.find()) {
        int start=matcher.start();
        int end=matcher.end();
        System.out.println("Match found" + text.substring(start,end) + " с "+ start + " By " + (end-1) + "position");
    }
    System.out.println(matcher.replaceFirst("Ira"));
    System.out.println(matcher.replaceAll("Olga"));
    System.out.println(text);
}
Résultat du programme : Une correspondance a été trouvée Alla de la 5e à la 8e position Une correspondance a été trouvée Anna de la 10e à la 13e position Egor Ira Anna Egor Olga Olga Egor Alla Anna D'après l'exemple, il est clair que les méthodes replaceFirstcréent replaceAllun nouvel objet String- une chaîne, qui est le texte source dans lequel les correspondances avec le modèle sont remplacées par le texte transmis à la méthode en tant qu'argument. De plus, la méthode replaceFirstremplace uniquement la première correspondance et replaceAlltoutes les correspondances du test. Le texte original reste inchangé. L'utilisation d'autres méthodes de classe Matcher, ainsi que des exemples d'expressions régulières, peuvent être trouvés dans cette série d'articles . Les opérations les plus courantes avec des expressions régulières lorsque vous travaillez avec du texte proviennent de classes Patternet Matchersont intégrées au fichier String. Ce sont des méthodes telles que split, matches, replaceFirst, replaceAll. Mais en fait, "sous le capot", ils utilisent le Patternet Matcher. Par conséquent, si vous devez remplacer du texte ou comparer des chaînes dans un programme sans écrire de code inutile, utilisez les méthodes du String. Si vous avez besoin de fonctionnalités avancées, pensez aux cours Patternet aux Matcher.

Conclusion

Une expression régulière est décrite dans un programme Java à l'aide de chaînes qui correspondent à un modèle défini par les règles. Lorsque le code s'exécute, Java recompile cette chaîne dans un objet de classe Patternet utilise l'objet de classe Matcherpour rechercher des correspondances dans le texte. Comme je le disais au début, les expressions régulières sont très souvent mises de côté pour plus tard, considérées comme un sujet difficile. Cependant, si vous comprenez les bases de la syntaxe, des métacaractères, de l'échappement et étudiez des exemples d'expressions régulières, elles s'avèrent beaucoup plus simples qu'il n'y paraît à première vue.
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION