Java Language
Expressions régulières
Recherche…
Introduction
Une expression régulière est une séquence spéciale de caractères qui aide à faire correspondre ou à trouver d'autres chaînes ou ensembles de chaînes, en utilisant une syntaxe spécialisée contenue dans un modèle. Java prend en charge l'utilisation des expressions régulières via le package java.util.regex
. Cette rubrique a pour but d’introduire et d’aider les développeurs à mieux comprendre les exemples d’utilisation des expressions régulières en Java.
Syntaxe
- Pattern patternName = Pattern.compile (regex);
- MatcherName matcherName = patternName.matcher (textToSearch);
- matcherName.matches () // Renvoie true si textToSearch correspond exactement à l'expression régulière
- matcherName.find () // Recherche dans textToSearch pour la première instance d'une sous-chaîne correspondant à l'expression régulière. Les appels suivants rechercheront le reste de la chaîne.
- matcherName.group (groupNum) // Retourne la sous-chaîne à l'intérieur d'un groupe de capture
- matcherName.group (groupName) // Retourne la sous-chaîne à l'intérieur d'un groupe de capture nommé (Java 7+)
Remarques
Importations
Vous devrez ajouter les importations suivantes avant de pouvoir utiliser Regex:
import java.util.regex.Matcher
import java.util.regex.Pattern
Pièges
Dans Java, une barre oblique inverse est échappée avec une double barre oblique inverse. Par conséquent, une barre oblique inverse dans la chaîne de regex doit être entrée en tant que double barre oblique inverse. Si vous avez besoin d'échapper à une double barre oblique inverse (pour faire correspondre une seule barre oblique inverse avec l'expression régulière, vous devez la saisir en tant que double barre oblique inverse).
Symboles importants expliqués
Personnage | La description |
---|---|
* | Correspondre au caractère précédent ou à la sous-expression 0 fois ou plus |
+ | Faire correspondre le caractère ou la sous-expression précédent 1 fois ou plus |
? | Faire correspondre le caractère ou la sous-expression précédent 0 ou 1 fois |
Lectures complémentaires
La rubrique regex contient plus d'informations sur les expressions régulières.
Utilisation de groupes de capture
Si vous devez extraire une partie de la chaîne de la chaîne d'entrée, vous pouvez utiliser des groupes de capture de regex.
Pour cet exemple, nous commencerons par une simple expression de numéro de téléphone:
\d{3}-\d{3}-\d{4}
Si des parenthèses sont ajoutées à l'expression rationnelle, chaque ensemble de parenthèses est considéré comme un groupe de capture . Dans ce cas, nous utilisons ce que l'on appelle des groupes de capture numérotés:
(\d{3})-(\d{3})-(\d{4})
^-----^ ^-----^ ^-----^
Group 1 Group 2 Group 3
Avant de pouvoir l'utiliser en Java, nous ne devons pas oublier de suivre les règles de Strings, en évitant les barres obliques inverses, ce qui entraîne le modèle suivant:
"(\\d{3})-(\\d{3})-(\\d{4})"
Nous devons d'abord compiler le modèle regex pour créer un Pattern
, puis nous avons besoin d'un Matcher
correspondant à notre chaîne d'entrée avec le pattern:
Pattern phonePattern = Pattern.compile("(\\d{3})-(\\d{3})-(\\d{4})");
Matcher phoneMatcher = phonePattern.matcher("abcd800-555-1234wxyz");
Ensuite, le Matcher doit trouver la première sous-séquence correspondant à l'expression régulière:
phoneMatcher.find();
Maintenant, en utilisant la méthode de groupe, nous pouvons extraire les données de la chaîne:
String number = phoneMatcher.group(0); //"800-555-1234" (Group 0 is everything the regex matched)
String aCode = phoneMatcher.group(1); //"800"
String threeDigit = phoneMatcher.group(2); //"555"
String fourDigit = phoneMatcher.group(3); //"1234"
Remarque: Matcher.group()
peut être utilisé à la place de Matcher.group(0)
.
Java 7 a introduit les groupes de capture nommés. Les groupes de capture nommés fonctionnent de la même manière que les groupes de capture numérotés (mais avec un nom au lieu d'un nombre), bien qu'il y ait de légères modifications de syntaxe. L'utilisation de groupes de capture nommés améliore la lisibilité.
Nous pouvons modifier le code ci-dessus pour utiliser des groupes nommés:
(?<AreaCode>\d{3})-(\d{3})-(\d{4})
^----------------^ ^-----^ ^-----^
AreaCode Group 2 Group 3
Pour obtenir le contenu de "AreaCode", nous pouvons utiliser à la place:
String aCode = phoneMatcher.group("AreaCode"); //"800"
Utilisation de regex avec un comportement personnalisé en compilant le modèle avec des indicateurs
Un Pattern
peut être compilé avec des flags, si le regex est utilisé en tant que String
, utilisez des modificateurs inline:
Pattern pattern = Pattern.compile("foo.", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
pattern.matcher("FOO\n").matches(); // Is true.
/* Had the regex not been compiled case insensitively and singlelined,
* it would fail because FOO does not match /foo/ and \n (newline)
* does not match /./.
*/
Pattern anotherPattern = Pattern.compile("(?si)foo");
anotherPattern.matcher("FOO\n").matches(); // Is true.
"foOt".replaceAll("(?si)foo", "ca"); // Returns "cat".
Caractères d'échappement
Généralement
Pour utiliser des caractères spécifiques à une expression régulière ( ?+|
Etc.) dans leur sens littéral, ils doivent être échappés. Dans les expressions rationnelles courantes, cela se fait par une barre oblique inverse \
. Cependant, comme il a une signification particulière dans les chaînes Java, vous devez utiliser une double barre oblique inverse \\
.
Ces deux exemples ne fonctionneront pas:
"???".replaceAll ("?", "!"); //java.util.regex.PatternSyntaxException
"???".replaceAll ("\?", "!"); //Invalid escape sequence
Cet exemple fonctionne
"???".replaceAll ("\\?", "!"); //"!!!"
Fractionnement d'une chaîne délimitée par un tuyau
Cela ne renvoie pas le résultat attendu:
"a|b".split ("|"); // [a, |, b]
Cela renvoie le résultat attendu:
"a|b".split ("\\|"); // [a, b]
Échapper à la barre oblique inverse \
Cela donnera une erreur:
"\\".matches("\\"); // PatternSyntaxException
"\\".matches("\\\"); // Syntax Error
Cela marche:
"\\".matches("\\\\"); // true
Correspondant à un littéral regex.
Si vous devez faire correspondre des caractères faisant partie de la syntaxe des expressions régulières, vous pouvez marquer tout ou partie du motif comme un littéral d'expression régulière.
\Q
marque le début du littéral regex. \E
marque la fin du littéral regex.
// the following throws a PatternSyntaxException because of the un-closed bracket
"[123".matches("[123");
// wrapping the bracket in \Q and \E allows the pattern to match as you would expect.
"[123".matches("\\Q[\\E123"); // returns true
Un moyen plus simple de le faire sans avoir à mémoriser les séquences d'échappement \Q
et \E
consiste à utiliser Pattern.quote()
"[123".matches(Pattern.quote("[") + "123"); // returns true
Ne correspondant pas à une chaîne donnée
Pour faire correspondre quelque chose qui ne contient pas une chaîne donnée, on peut utiliser la lecture négative:
Syntaxe de regex: (?!string-to-not-match)
Exemple:
//not matching "popcorn"
String regexString = "^(?!popcorn).*$";
System.out.println("[popcorn] " + ("popcorn".matches(regexString) ? "matched!" : "nope!"));
System.out.println("[unicorn] " + ("unicorn".matches(regexString) ? "matched!" : "nope!"));
Sortie:
[popcorn] nope!
[unicorn] matched!
Correspondant à une barre oblique inverse
Si vous souhaitez faire correspondre une barre oblique inverse dans votre expression régulière, vous devrez y échapper.
La barre oblique inverse est un caractère d'échappement dans les expressions régulières. Vous pouvez utiliser '\\' pour faire référence à une seule barre oblique inverse dans une expression régulière.
Cependant, la barre oblique inverse est également un caractère d'échappement dans les chaînes de caractères Java. Pour créer une expression régulière à partir d'un littéral de chaîne, vous devez échapper à chacune de ses barres obliques inverses. Dans une chaîne, le littéral '\\\\' peut être utilisé pour créer une expression régulière avec '\\', qui à son tour peut correspondre à '\'.
Par exemple, considérez la correspondance de chaînes comme "C: \ dir \ myfile.txt". Une expression régulière ([A-Za-z]):\\(.*)
Correspondra et fournira la lettre de lecteur en tant que groupe de capture. Notez le double backslash.
Pour exprimer ce modèle dans un littéral de chaîne Java, chacune des barres obliques inverses de l'expression régulière doit être échappée.
String path = "C:\\dir\\myfile.txt";
System.out.println( "Local path: " + path ); // "C:\dir\myfile.txt"
String regex = "([A-Za-z]):\\\\.*"; // Four to match one
System.out.println("Regex: " + regex ); // "([A-Za-z]):\\(.*)"
Pattern pattern = Pattern.compile( regex );
Matcher matcher = pattern.matcher( path );
if ( matcher.matches()) {
System.out.println( "This path is on drive " + matcher.group( 1 ) + ":.");
// This path is on drive C:.
}
Si vous voulez faire correspondre deux barres obliques inverses, vous vous retrouverez à utiliser huit dans une chaîne littérale, pour représenter quatre dans l'expression régulière, pour correspondre à deux.
String path = "\\\\myhost\\share\\myfile.txt";
System.out.println( "UNC path: " + path ); // \\myhost\share\myfile.txt"
String regex = "\\\\\\\\(.+?)\\\\(.*)"; // Eight to match two
System.out.println("Regex: " + regex ); // \\\\(.+?)\\(.*)
Pattern pattern = Pattern.compile( regex );
Matcher matcher = pattern.matcher( path );
if ( matcher.matches()) {
System.out.println( "This path is on host '" + matcher.group( 1 ) + "'.");
// This path is on host 'myhost'.
}