Remarques sur l'utilisation des expressions régulières en Java

Diverses notes sur l'utilisation des expressions régulières en Java.

Méthodes qui utilisent des expressions régulières dans la classe String

Il existe plusieurs méthodes dans String qui acceptent les expressions régulières.

matches(String)

package sample.regexp;

public class Main {

    public static void main(String[] args) {
        String text = "abc123";

        System.out.println(text.matches("[a-z0-9]+"));
        System.out.println(text.matches("[a-z]+"));
    }
}

Résultat d'exécution


true
false

--Vérifiez que la chaîne correspond ** exactement ** à l'expression régulière spécifiée --Si seulement une partie correspond, ce sera faux

replaceAll(String, String)

package sample.regexp;

public class Main {

    public static void main(String[] args) {
        String text = "abc123";

        System.out.println(text.replaceAll("[a-z]", "*"));
    }
}

Résultat d'exécution


***123

--Passez une expression régulière comme premier argument et remplacez toutes les parties correspondantes par la chaîne de caractères du deuxième argument

Utilisez le groupe qui correspond à la chaîne de remplacement

package sample.regexp;

public class Main {

    public static void main(String[] args) {
        String text = "<<abc123>>";

        System.out.println(text.replaceAll("([a-z]+)([0-9]+)", "$0, $1, $2"));
    }
}

Résultat d'exécution


<<abc123, abc, 123>>

replaceFirst(String, String)

package sample.regexp;

public class Main {

    public static void main(String[] args) {
        String text = "abc123";

        System.out.println(text.replaceFirst("[a-z]", "*"));
    }
}

Résultat d'exécution


*bc123

--Remplacez uniquement la première partie correspondante de la sous-chaîne qui correspond à l'expression régulière --La sous-chaîne peut être référencée avec $ n, qui est identique à replaceAll ().

split(String, int)

package sample.regexp;

import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        String text = "a1b2";
        
        for (int i=-1; i<5; i++) {
            String[] elements = text.split("[0-9]", i);
            System.out.println("limit=" + i + ",\telements=" + Arrays.toString(elements));
        }
    }
}

Résultat d'exécution


limit=-1,	elements=[a, b, ]
limit=0,	elements=[a, b]
limit=1,	elements=[a1b2]
limit=2,	elements=[a, b2]
limit=3,	elements=[a, b, ]
limit=4,	elements=[a, b, ]

--Split la chaîne à l'emplacement qui correspond à l'expression régulière spécifiée dans le premier argument

Si le début devient vide suite à la division, le blanc est défini comme un élément du tableau tel quel.

package sample.regexp;

import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        String text = "0a1b2";
        
        String[] elements = text.split("[0-9]", 0);
        System.out.println(Arrays.toString(elements));
    }
}

Résultat d'exécution


[, a, b]

split(String) C'est le même comportement que de définir le deuxième argument de split (String, int) sur 0.

Classe de modèle

Différence par rapport à la méthode String

À quelques exceptions près [^ 1], méthodes qui utilisent la délégation canonique de la classe String à la classe Pattern dans les coulisses. Par exemple, si vous vérifiez l'implémentation de la méthode replaceAll (), cela ressemble à ceci:

String.replaceAll()


    public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
    }

Cette classe Pattern (et Matcher) est en charge du traitement des expressions régulières en Java.

La classe «Pattern» interprète la chaîne passée par «compile ()» comme une expression régulière. Si l'expression régulière utilisée est fixe, il est plus efficace d'exécuter cette compile () seulement la première fois, puis de réutiliser l'instance Pattern. (La classe Pattern est immuable, elle peut donc être réutilisée en toute sécurité même en multithreading.)

Cependant, ce compile () est exécuté à chaque fois lors de l'utilisation de la méthode qui utilise l'expression régulière de la classe String. Par conséquent, si vous utilisez la méthode String lorsque vous souhaitez exécuter une expression régulière fixe encore et encore, la vitesse de traitement sera plus lente que l'utilisation de l'instance Pattern.

Exemple d'utilisation de Pattern


public class Hoge {
    //Réutiliser l'instance de Pattern compilée
    private static final Pattern HOGE_PATTERN = Pattern.compile("[0-9]+");

    public boolean test(String text) {
        return HOGE_PATTERN.matcher(text).matches(); //Le mouvement est texte.maches("[0-9]+")Pareil que
    }
}

Utilisation de base

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        Pattern pattern = Pattern.compile("[0-9]+");
        
        Matcher abc = pattern.matcher("123abc");
        System.out.println(abc.matches());

        Matcher _123 = pattern.matcher("123");
        System.out.println(_123.matches());
    }
}

Résultat d'exécution


false
true

Divisé

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.Arrays;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        Pattern pattern = Pattern.compile("[a-z]+");

        String[] elements = pattern.split("123abc456def789ghi");
        System.out.println(Arrays.toString(elements));

        elements = pattern.split("123abc456def789ghi", -1);
        System.out.println(Arrays.toString(elements));
    }
}

Résultat d'exécution


[123, 456, 789]
[123, 456, 789, ]

--Avec Pattern.split (String), divisez la chaîne au niveau de la partie de la chaîne spécifiée qui correspond à l'expression régulière.

Matcher --Pattern est une classe qui interprète les expressions régulières et Matcher effectue le traitement suivant.

  1. Effectuez une opération de match
  2. Interrogez le résultat de l'opération de correspondance
  3. Répétez les étapes 1 et 2 si nécessaire --Le résultat de l'opération de correspondance peut être référencé par la méthode suivante. --start () Début de l'index sur la séquence d'entrée correspondante --ʻEnd () ʻEnd index sur la séquence d'entrée correspondante + 1 --group () Sous-chaîne correspondante --Si vous exécutez ces méthodes sans effectuer d'opération de correspondance, ʻIllegalStateException` sera levé.

Opération de match

Il y a trois opérations de match dans Matcher.

matches()

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        test("abc");
        test("abc123");
    }

    private static void test(String text) {
        Pattern pattern = Pattern.compile("[a-z]+");
        Matcher matcher = pattern.matcher(text);

        System.out.println("[text=" + text + "]");
        if (matcher.matches()) {
            System.out.println("matches = true");
            System.out.println("start = " + matcher.start());
            System.out.println("end = " + matcher.end());
            System.out.println("group = " + matcher.group());
        } else {
            System.out.println("matches = false");
        }
    }
}

Résultat d'exécution


[text=abc]
matches = true
start = 0
end = 3
group = abc

[text=abc123]
matches = false

--matches () vérifie que toute la séquence d'entrée correspond à l'expression régulière --Retourne true si la correspondance est établie

lookingAt()

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        test("abc");
        test("123abc");
        test("ab12");
    }

    private static void test(String text) {
        Pattern pattern = Pattern.compile("[a-z]+");
        Matcher matcher = pattern.matcher(text);

        System.out.println("[text=" + text + "]");
        if (matcher.lookingAt()) {
            System.out.println("lookingAt = true");
            System.out.println("start = " + matcher.start());
            System.out.println("end = " + matcher.end());
            System.out.println("group = " + matcher.group());
        } else {
            System.out.println("lookingAt = false");
        }
    }
}

Résultat d'exécution


[text=abc]
lookingAt = true
start = 0
end = 3
group = abc

[text=123abc]
lookingAt = false

[text=ab12]
lookingAt = true
start = 0
end = 2
group = ab

--lookingAt () vérifie que l'expression régulière correspond au début de la séquence d'entrée --Si la vérification résulte du début de la correspondance, true est renvoyé (le tout ne doit pas nécessairement correspondre)

find()

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        test("abc");
        test("123abc456def789");
    }

    private static void test(String text) {
        Pattern pattern = Pattern.compile("[a-z]+");
        Matcher matcher = pattern.matcher(text);

        System.out.println("[text=" + text + "]");
        while (matcher.find()) {
            System.out.println("start = " + matcher.start());
            System.out.println("end = " + matcher.end());
            System.out.println("group = " + matcher.group());
        }
    }
}

Résultat d'exécution


[text=abc]
start = 0
end = 3
group = abc

[text=123abc456def789]
start = 3
end = 6
group = abc

start = 9
end = 12
group = def

Remplacement

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        Pattern pattern = Pattern.compile("[a-z]+");
        Matcher matcher = pattern.matcher("abc123def");

        System.out.println("replaceAll = " + matcher.replaceAll("*"));
        System.out.println("replaceFirst = " + matcher.replaceFirst("*"));
    }
}

Résultat d'exécution


replaceAll = *123*
replaceFirst = *123def

--Remplacez toutes les sous-chaînes correspondantes par Matcher.replaceAll (String) --Matcher.replaceFirst (String) remplace uniquement la première sous-chaîne correspondante

groupe

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        Pattern pattern = Pattern.compile("([a-z]+)([0-9]+)");
        Matcher matcher = pattern.matcher("abc123de45fg");

        int groupCount = matcher.groupCount();
        System.out.println("groupCount=" + groupCount);
        
        while (matcher.find()) {
            System.out.println("==========");
            String group = matcher.group();
            System.out.println("group=" + group);
            
            for (int i=0; i<=groupCount; i++) {
                String g = matcher.group(i);
                System.out.println("group(" + i + ")=" + g);
            }
        }
    }
}

Résultat d'exécution


groupCount=2
==========
group=abc123
group(0)=abc123
group(1)=abc
group(2)=123
==========
group=de45
group(0)=de45
group(1)=de
group(2)=45

Donnez un nom au groupe

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        Pattern pattern = Pattern.compile("(?<alphabets>[a-z]+)(?<numbers>[0-9]+)");
        Matcher matcher = pattern.matcher("abc123de45fg");
        
        while (matcher.find()) {
            System.out.println("==========");
            System.out.println("group(alphabets)=" + matcher.group("alphabets"));
            System.out.println("group(numbers)=" + matcher.group("numbers"));
        }
    }
}

Résultat d'exécution


==========
group(alphabets)=abc
group(numbers)=123
==========
group(alphabets)=de
group(numbers)=45

Pour faire référence au nom du groupe dans la chaîne de remplacement, procédez comme suit:

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        Pattern pattern = Pattern.compile("(?<alphabets>[a-z]+)(?<numbers>[0-9]+)");
        Matcher matcher = pattern.matcher("abc123def456");

        String replaced = matcher.replaceAll("${numbers}${alphabets}");
        System.out.println(replaced);
    }
}

Résultat d'exécution


123abc456def

drapeau

--Lors de la création d'une instance Pattern, vous pouvez ajuster la façon dont l'expression régulière est interprétée avec le ** flag **.

Compiler avec des indicateurs


Pattern pattern = Pattern.compile("[a-z]", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

CASE_INSENSITIVE (insensible à la casse)

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        Pattern pattern = Pattern.compile("[a-z]+", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher("ABC");
        System.out.println(matcher.matches());
    }
}

Résultat d'exécution


true

--Si vous spécifiez CASE_INSENSITIVE, la correspondance est insensible à la casse.

UNICODE_CASE (Unicode est insensible à la casse)

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        Pattern pattern = Pattern.compile("[a-zA-Z]+", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
        Matcher matcher = pattern.matcher("ABCabc");
        System.out.println(matcher.matches());
    }
}

Résultat d'exécution


true

LITERAL (n'utilisez pas de méta-caractères d'expression régulière ni de caractères d'échappement)

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        Pattern pattern = Pattern.compile("[a-z]+", Pattern.LITERAL);
        
        Matcher matcher = pattern.matcher("abc");
        System.out.println(matcher.matches());
        
        matcher = pattern.matcher("[a-z]+");
        System.out.println(matcher.matches());
    }
}

Résultat d'exécution


false
true

--Si LITERAL est spécifié, la chaîne de caractères passée dans le premier argument de` compile (String, int) ʻest traitée comme une simple chaîne de caractères.

MULTILINE (traite les chaînes multilignes)

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        test("[default]", () -> Pattern.compile("^[a-z]+$"));
        test("[MULTILINE]", () -> Pattern.compile("^[a-z]+$", Pattern.MULTILINE));
    }
    
    private static void test(String label, Supplier<Pattern> patternSupplier) {
        System.out.println(label);
        Pattern pattern = patternSupplier.get();

        String text = "abc\n"
                    + "def\n";

        Matcher matcher = pattern.matcher(text);

        while (matcher.find()) {
            String group = matcher.group();
            System.out.println(group);
        }
    }
}

Résultat d'exécution


[default]
[MULTILINE]
abc
def

--Lorsque MULTILINE est spécifié, la gestion de ^ ʻet ` représentant le début et la fin des lignes change. --Si rien n'est spécifié, «^» et «» correspondent uniquement au début et à la fin de la chaîne. --Si MULTILINE est spécifié, chacun séparé par un saut de ligne est traité comme une chaîne de caractères, donc ^ ʻet $` correspondront au début et à la fin de chaque ligne.

COMMENTAIRES (vous permet d'écrire des commentaires)

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        String regexp = "#Cette ligne est ignorée en tant que commentaire\n"
                      + "  [a-z]+  ";
        Pattern pattern = Pattern.compile(regexp, Pattern.COMMENTS);

        Matcher matcher = pattern.matcher("abc");

        System.out.println(matcher.matches());
    }
}

Résultat d'exécution


true

--Si «COMMENTAIRES» est spécifié, les chaînes de caractères suivantes seront traitées comme des commentaires et ignorées. --De # à la fin de la ligne --Espace vide

DOTALL (assurez-vous de faire correspondre la fin de la ligne avec .)

package sample.regexp;

import org.openjdk.jmh.runner.RunnerException;

import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) throws RunnerException {
        test("[default1]", () -> Pattern.compile(".+"));
        test("[default2]", () -> Pattern.compile(".+$"));
        test("[DOTALL]", () -> Pattern.compile(".+", Pattern.DOTALL));
    }

    private static void test(String label, Supplier<Pattern> patternSupplier) {
        System.out.println(label);
        Pattern pattern = patternSupplier.get();

        String text = "abc\n"
                    + "def\n";

        Matcher matcher = pattern.matcher(text);

        if (matcher.find()) {
            String group = matcher.group();
            System.out.println(group);
        }
    }
}

Résultat d'exécution


[default1]
abc
[default2]
def
[DOTALL]
abc
def

--Si DOTALL est spécifié, . correspondra également à la fin de la ligne. --Par défaut, . ne correspond pas à la fin de la ligne

référence

[^ 1]: Par exemple, la méthode split (String regexp) effectue un traitement fractionné sans utiliser Pattern lorsque regexp est une chaîne de caractères simples qui n'utilise pas les méta-caractères des expressions régulières. En train d'aller

Recommended Posts

Remarques sur l'utilisation des expressions régulières en Java
Comment utiliser les classes en Java?
Comment utiliser les expressions Java lambda
Prise en charge multilingue de Java Comment utiliser les paramètres régionaux
Notes sur les expressions régulières
Notes sur l'utilisation de chaque règle de JUnit
Notes sur la façon de rédiger des commentaires en anglais
[Java] Comment utiliser Map
Comment utiliser java Facultatif
Comment utiliser la classe Java
Comment utiliser Java Map
Comment utiliser les variables Java
Comment utiliser la bibliothèque non standard Java sur IntelliJ IDEA
[Java] Comment exécuter des tâches régulièrement
Comment utiliser HttpClient de Java (Post)
[Java] Comment utiliser la méthode de jointure
Comment utiliser Ruby on Rails
Comment apprendre JAVA en 7 jours
Comment utiliser les bio-formats sur Ubuntu 20.04
[Traitement × Java] Comment utiliser les variables
Remarques sur le contrôle du signal en Java
Comment utiliser InjectorHolder dans OpenAM
[JavaFX] [Java8] Comment utiliser GridPane
Comment utiliser les méthodes de classe [Java]
[Java] Comment utiliser List [ArrayList]
Comment nommer des variables en Java
[Traitement × Java] Comment utiliser les tableaux
[Java] Comment utiliser la classe Math
Comment utiliser le type enum Java
Comment concaténer des chaînes avec Java
Comment utiliser les données JSON dans la communication WebSocket (Java, JavaScript)
Comment appeler et utiliser l'API en Java (Spring Boot)
Comment utiliser le type d'énumération Java (Enum) dans Mapper XML de MyBatis
Comment changer Java à l'ère d'OpenJDK sur Mac
Comment vérifier Java installé sur Mac
Un mémorandum sur l'utilisation d'Eclipse
Comment implémenter le calcul de la date en Java
Comment implémenter le filtre de Kalman par Java
Comment utiliser Apache Derby sur Eclipse
[Java] Comment utiliser la classe File
Comment utiliser le volume nommé dans docker-compose.yml
Comment utiliser la méthode de soumission (Java Silver)
Comment faire une conversion de base en Java
[Java] Comment utiliser la méthode toString ()
Etudier comment utiliser le constructeur (java)
Comment faire fonctionner automatiquement un écran créé en Java sous Windows
[Traitement × Java] Comment utiliser la boucle
Comment utiliser Docker dans VSCode DevContainer
Comment changer de version de Java sur Mac
Comment utiliser MySQL dans le didacticiel Rails
Comment appliquer les conventions de codage en Java
Comment utiliser et définir les classes Java, importer
Comment intégrer Janus Graph dans Java