JavaRush /Blog Java /Random-FR /Expressions régulières en Java, partie 3

Expressions régulières en Java, partie 3

Publié dans le groupe Random-FR
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 3 - 1Expressions régulières en Java, partie 1 Expressions régulières en Java, partie 2

Simplifiez les tâches de programmation courantes avec l'API Regex

Dans les parties 1 et 2 de cet article, vous avez découvert les expressions régulières et l'API Regex. Vous avez découvert le cours Patternet parcouru des exemples illustrant les constructions d'expressions régulières, de la simple correspondance de modèles utilisant des chaînes littérales à la correspondance plus complexe utilisant des plages, des comparateurs de limites et des quantificateurs. Dans cette partie et les suivantes, nous examinerons les questions non abordées dans la première partie, nous étudierons les méthodes correspondantes des classes Pattern, Matcheret PatternSyntaxException. Vous apprendrez également deux utilitaires qui utilisent des expressions régulières pour faciliter les problèmes de programmation courants. Le premier extrait les commentaires du code pour la documentation. La seconde est une bibliothèque de code réutilisable conçue pour effectuer une analyse lexicale – un composant essentiel des assembleurs, compilateurs et logiciels similaires.

TÉLÉCHARGEMENT DU CODE SOURCE

Vous pouvez obtenir tout le code source (créé par Jeff Friesen pour JavaWorld) pour les applications de démonstration de cet article à partir d'ici .

Apprendre l'API Regex

Pattern, Matcheret PatternSyntaxExceptionsont les trois classes qui composent l'API Regex. Chacun d'eux fournit des méthodes qui vous permettent d'utiliser des expressions régulières dans votre code.

Méthodes de la classe Pattern

Une instance d'une classe Patternest une expression régulière compilée, également appelée modèle. Les expressions régulières sont compilées pour améliorer les performances des opérations de correspondance de modèles. Les méthodes statiques suivantes prennent en charge la compilation.
  • Pattern compile(String regex)compile le contenu regexdans une représentation intermédiaire stockée dans un nouveau fichier Pattern. Cette méthode renvoie une référence à un objet en cas de succès ou lève une exception PatternSyntaxExceptionsi une syntaxe d'expression régulière non valide est détectée. Tout objet de la classe Matcherutilisé par Patternou renvoyé par cet objet utilise ses paramètres par défaut, tels que la recherche sensible à la casse. À titre d'exemple, l'extrait de code Pattern p = Pattern.compile("(?m)^\\."); crée un objet Patternqui stocke une représentation compilée d'une expression régulière pour faire correspondre les chaînes commençant par un point.

  • Pattern compile(String regex, int flags)résout le même problème que Pattern compile(String regex), mais en prenant en compte flags: un ensemble de constantes binaires pour les indicateurs binaires de type OU. La classe Patterndéclare des constantes CANON_EQ, CASE_INSENSITIVE, COMMENTS, DOTALL, LITERAL, MULTILINE, UNICODE_CASE, UNICODE_CHARACTER_CLASS и UNIX_LINESqui peuvent être combinées à l'aide d'un OU au niveau du bit (par exemple, CASE_INSENSITIVE | DOTALL) et transmises en argument flags.

  • À l'exception de CANON_EQ, LITERAL и UNICODE_CHARACTER_CLASS, ces constantes sont une alternative aux expressions d'indicateur imbriquées présentées dans la première partie. Si une constante d'indicateur autre que celles définies dans la classe est rencontrée Pattern, la méthode Pattern compile(String regex, int flags) lève une exception java.lang.IllegalArgumentException. Par exemple, Pattern p = Pattern.compile("^\\.", Pattern.MULTILINE);équivalent à l'exemple précédent, avec la constante Pattern.MULTILINEet l'expression d'indicateur imbriquée (?m)faisant la même chose.
Parfois, il est nécessaire d'obtenir une copie de la chaîne originale d'une expression régulière compilée dans un objet Pattern, ainsi que les indicateurs qu'elle utilise. Pour ce faire, vous pouvez appeler les méthodes suivantes :
  • String pattern()renvoie la chaîne d'expression régulière d'origine compilée dans un fichier Pattern.

  • int flags()renvoie les drapeaux de l'objet Pattern.
Après avoir reçu l'objet Pattern, il est généralement utilisé pour obtenir l'objet Matcherafin d'effectuer des opérations de correspondance de modèles. La méthode Matcher matcher(Charsequence input)crée un objet Matcherqui recherche dans le texte inputune correspondance avec un modèle d'objet Pattern. Lorsqu'il est appelé, il renvoie une référence à cet objet Matcher. Par exemple, la commande Matcher m = p.matcher(args[1]);renvoie Matcherl'objet Patternréférencé par la variable p.
Recherche unique
La méthode static boolean matches(String regex, CharSequence input)de classe Patternvous permet d'économiser sur la création d'objets Patternet Matcherla recherche unique à l'aide d'un modèle. Cette méthode renvoie true si inputle modèle correspond regex, sinon elle renvoie false. Si l'expression régulière contient une erreur de syntaxe, la méthode lève une exception PatternSyntaxException. Par exemple, System.out.println(Pattern.matches("[a-z[\\s]]*", "all lowercase letters and whitespace only"));imprime true, confirmant que la phrase all lowercase letters and whitespace onlyne contient que des espaces et des caractères minuscules.
Expressions régulières en Java, parties 3 à 2

Fractionner le texte

La plupart des développeurs ont au moins une fois écrit du code pour diviser le texte saisi en ses composants, comme la conversion d'un compte d'employé basé sur du texte en un ensemble de champs. La classe Patternoffre la possibilité de résoudre plus facilement cette tâche fastidieuse en utilisant deux méthodes de fractionnement de texte :
  • La méthode String[] split(CharSequence text, int limit)se divise texten fonction des correspondances trouvées avec le modèle d'objet Patternet renvoie les résultats dans un tableau. Chaque élément du tableau spécifie une séquence de texte séparée de la séquence suivante par un fragment de texte correspondant à un motif (ou une fin de texte). Les éléments du tableau sont dans le même ordre dans lequel ils apparaissent dans text.

    Dans cette méthode, le nombre d'éléments du tableau dépend du paramètre limit, qui contrôle également le nombre de correspondances à trouver.

    • Une valeur positive ne recherche pas plus de limit-1correspondances et la longueur du tableau ne dépasse pas limitles éléments.
    • Si la valeur est négative, toutes les correspondances possibles sont recherchées et la longueur du tableau peut être arbitraire.
    • Si la valeur est zéro, toutes les correspondances possibles sont recherchées, la longueur du tableau peut être arbitraire et les lignes vides à la fin sont supprimées.

  • La méthode String[] split(CharSequence text)appelle la méthode précédente avec 0 comme argument limite et renvoie le résultat de son appel.
Vous trouverez ci-dessous les résultats de la méthode split(CharSequence text)permettant de résoudre le problème de la division d'un compte d'employé en champs distincts de nom, d'âge, d'adresse postale et de salaire :

Pattern p = Pattern.compile(",\\s");
String[] fields = p.split("John Doe, 47, Hillsboro Road, 32000");
for (int i = 0; i < fields.length; i++)
   System.out.println(fields[i]);
Le code ci-dessus décrit une expression régulière pour rechercher un caractère virgule immédiatement suivi d'un seul caractère espace. Voici les résultats de son exécution :

John Doe
47
Hillsboro Road
32000

Prédicats de modèle et API Streams

En Java 8, Patternune méthode est apparue dans la classe . Cette méthode crée un prédicat (une fonction avec une valeur booléenne) qui est utilisé pour correspondre au modèle. L'utilisation de cette méthode est illustrée dans l'extrait de code suivant : Predicate asPredicate()
List progLangs = Arrays.asList("apl", "basic", "c", "c++", "c#", "cobol", "java", "javascript", "perl", "python", "scala");
Pattern p = Pattern.compile("^c");
progLangs.stream().filter(p.asPredicate()).forEach(System.out::println);
Ce code crée une liste de noms de langages de programmation, puis compile un modèle pour rechercher tous les noms commençant par la lettre c. La dernière ligne de code ci-dessus implémente la réception d'un flux de données en série avec cette liste comme source. Il configure un filtre à l'aide d'une fonction booléenne asPredicate()qui renvoie vrai lorsque le nom commence par une lettre cet parcourt le flux, imprimant les noms correspondants sur la sortie standard. Cette dernière ligne est équivalente à la boucle régulière suivante, familière de l'application RegexDemo de la partie 1 :

for (String progLang: progLangs) 
   if (p.matcher(progLang).find())
      System.out.println(progLang);

Méthodes de classe Matcher

Une instance de la classe Matcherdécrit un mécanisme permettant d'effectuer des opérations de correspondance de modèles sur une séquence de caractères en interprétant l'expression régulière compilée de la classe Pattern. Les objets de la classe Matcherprennent en charge différents types d'opérations de recherche de modèles :
  • La méthode boolean find()recherche dans le texte saisi la correspondance suivante. Cette méthode commence l'analyse soit au début du texte spécifié, soit au premier caractère après la correspondance précédente. La deuxième option n'est possible que si l'appel précédent à cette méthode a renvoyé vrai et que le résolveur n'a pas été réinitialisé. Dans tous les cas, si la recherche réussit, la valeur booléenne true est renvoyée. Un exemple de cette méthode peut être trouvé dans RegexDemola partie 1.

  • La méthode boolean find(int start)réinitialise le matcher et recherche dans le texte la correspondance suivante. La visualisation commence à partir de la position spécifiée par le paramètre start. Si la recherche réussit, la valeur booléenne true est renvoyée. Par exemple, m.find(1);analyse le texte à partir de la position 1(la position 0 est ignorée). Si le paramètre startcontient une valeur négative ou une valeur supérieure à la longueur du texte du correspondant, la méthode lève une exception java.lang.IndexOutOfBoundsException.

  • La méthode boolean matches()tente de faire correspondre tout le texte à un modèle. Il renvoie une valeur booléenne vraie si tout le texte correspond au modèle. Par exemple, le code Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.matches());est généré falsecar le caractère !n'est pas un caractère de mot.

  • La méthode boolean lookingAt()essaie de faire correspondre le texte spécifié avec le modèle. Cette méthode renvoie vrai si une partie du texte correspond au modèle. Contrairement à la méthode matches();, tout le texte ne doit pas nécessairement correspondre au modèle. Par exemple, Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.lookingAt());il affichera true, puisque le début du texte abc!se compose uniquement de caractères formant des mots.

Contrairement aux objets de classe Pattern, les objets de classe Matcherconservent les informations d'état. Parfois, vous devrez peut-être réinitialiser le matcher pour effacer ces informations une fois la recherche de modèles terminée. Les méthodes suivantes sont disponibles pour réinitialiser le résolveur :
  • La méthode Matcher reset()réinitialise l'état du matcher, y compris la position à ajouter à la fin (réinitialisée à 0). L'opération de recherche de modèle suivante commence au début du texte du correspondant. Renvoie une référence à l'objet actuel Matcher. Par exemple, m.reset();réinitialise le résolveur référencé par m.

  • La méthode Matcher reset(CharSequence text)réinitialise l’état du résolveur et définit le nouveau texte du résolveur sur text. L'opération de recherche de modèle suivante commence au début du nouveau texte de correspondance. Renvoie une référence à l'objet actuel Matcher. Par exemple, m.reset("new text");réinitialise le résolveur référencé met définit le nouveau texte du résolveur sur "new text".

Expressions régulières en Java, parties 3 à 3

Ajouter du texte à la fin

La position du matcher à ajouter à la fin spécifie le début du texte du matcher qui est ajouté à la fin de l'objet de type java.lang.StringBuffer. Les méthodes suivantes utilisent cette position :
  • La méthode Matcher appendReplacement(StringBuffer sb, String replacement)lit les caractères du texte du matcher et les ajoute à la fin de l'objet StringBufferréférencé par l'argument sb. Cette méthode arrête la lecture au dernier caractère précédant la correspondance de modèle précédente. Ensuite, la méthode ajoute les caractères de l'objet de type Stringréférencé par l'argument replacementà la fin de l'objet StringBuffer(la chaîne replacementpeut contenir des références à des séquences de texte capturées lors de la recherche précédente ; celles-ci sont spécifiées à l'aide des caractères ($)et des numéros de groupe capturés). Enfin, la méthode définit la valeur de la position du matcher à ajouter à la position du dernier caractère correspondant plus un, puis renvoie une référence au matcher actuel.

  • La méthode Matcher appendReplacement(StringBuffer sb, String replacement)lève une exception java.lang.IllegalStateExceptionsi le comparateur n'a pas encore trouvé de correspondance ou si une tentative de recherche précédente a échoué. Il lève une exception IndexOutOfBoundsExceptionsi la ligne replacementspécifie un groupe de capture qui n'est pas dans le modèle).

  • La méthode StringBuffer appendTail(StringBuffer sb)ajoute tout le texte à un objet StringBufferet renvoie une référence à cet objet. Après le dernier appel de méthode appendReplacement(StringBuffer sb, String replacement), appelez la méthode appendTail(StringBuffer sb)pour copier le texte restant dans l'objet StringBuffer.

Groupes capturés
Comme vous vous en souvenez de la première partie, un groupe de capture est une séquence de caractères entourés de ()métacaractères entre parenthèses ( ). Le but de cette construction est de stocker les caractères trouvés pour une réutilisation ultérieure lors de la correspondance de modèles. Tous les caractères du groupe capturé sont considérés comme un tout lors de la recherche de modèles.
Le code suivant appelle les méthodes appendReplacement(StringBuffer sb, String replacement)et appendTail(StringBuffer sbpour remplacer toutes les occurrences de la séquence de caractères dans le texte source catparcaterpillar :

Pattern p = Pattern.compile("(cat)");
Matcher m = p.matcher("one cat, two cats, or three cats on a fence");
StringBuffer sb = new StringBuffer();
while (m.find())
   m.appendReplacement(sb, "$1erpillar");
m.appendTail(sb);
System.out.println(sb);
L'utilisation d'un groupe capturé et d'une référence à celui-ci dans le texte de remplacement indique au programme d'insérer erpillaraprès chaque occurrence de cat. Le résultat de l'exécution de ce code ressemble à ceci : one caterpillar, two caterpillars, or three caterpillars on a fence

Remplacement du texte

La classe Matchernous propose deux méthodes de remplacement de texte, complémentaires au appendReplacement(StringBuffer sb, String replacement). En utilisant ces méthodes, vous pouvez remplacer soit la première occurrence du [texte remplacé], soit toutes les occurrences :
  • La méthode String replaceFirst(String replacement)réinitialise le matcher, crée un nouvel objet String, copie tous les caractères du texte du matcher (jusqu'à la première correspondance) dans cette chaîne, ajoute les caractères à la fin de celle-ci replacement, copie les caractères restants dans la chaîne et renvoie un objet String(la chaîne replacementpeut contenir des références à celles capturées lors des séquences de texte de recherche précédentes à l'aide de symboles dollar et de numéros de groupe capturés).

  • La méthode String replaceAll(String replacement)fonctionne de manière similaire à la méthode String replaceFirst(String replacement), mais remplace replacementtoutes les correspondances trouvées par des caractères de la chaîne.

Une expression régulière \s+recherche un ou plusieurs caractères d'espacement dans le texte saisi. Ci-dessous, nous utiliserons cette expression régulière et appellerons une méthode replaceAll(String replacement)pour supprimer les espaces en double :

Pattern p = Pattern.compile("\\s+");
Matcher m = p.matcher("Удаляем      \t\t лишние пробелы.   ");
System.out.println(m.replaceAll(" "));
Voici les résultats : Удаляем лишние пробелы. Expressions régulières en Java, partie 4 Expressions régulières en Java, partie 5
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION