Regex ne fonctionne pas dans String.matches ()


147

J'ai ce petit bout de code

String[] words = {"{apf","hum_","dkoe","12f"};
for(String s:words)
{
    if(s.matches("[a-z]"))
    {
        System.out.println(s);
    }
}

Censé imprimer

dkoe

mais ça n'imprime rien !!


41
Java matchesmet un ^ au début et un $ à la fin des expressions rationnelles pour vous. Donc matches("[a-z]")recherchera en fait / ^ [az] $ / à la place.
Robino

Oui @Robino vous avez absolument raison.
Mihir

1
Sûrement, si vous prévoyez matchesde rechercher une occurrence de [a-z], alors il devrait correspondre à tous? Je ne m'attendrais pas matchesà vérifier chaque caractère individuellement par rapport à l'expression régulière.
PhilHibbs

@Robino: Où cette fonctionnalité est-elle décrite / documentée?
Toru le

@Toru Sur la page de documentation java pour String.Matches - où d'autre? Un Google occasionnel de "java string matches documentation" révèle, dans le premier résultat, l'expression "str.matches (regex) donne exactement le même résultat que l'expression". Le mot important est «exactement».
Robino le

Réponses:


323

Bienvenue dans la .matches()méthode mal nommée de Java ... Elle essaie et correspond à TOUTES les entrées. Malheureusement, d'autres langues ont emboîté le pas :(

Si vous voulez voir si l'expression régulière correspond à un texte d'entrée, utilisez a Pattern, a Matcheret la .find()méthode du matcher:

Pattern p = Pattern.compile("[a-z]");
Matcher m = p.matcher(inputstring);
if (m.find())
    // match

Si vous voulez effectivement voir si une entrée ne contient que des lettres minuscules, vous pouvez utiliser .matches(), mais vous devez faire correspondre un ou plusieurs caractères: ajoutez un +à votre classe de caractères, comme dans [a-z]+. Ou utilisez ^[a-z]+$et .find().


2
Je trouve des centaines de tutoriels incomplets en ligne. Je n'ai pas pu en trouver un bon. Avez-vous des suggestions?
John

Merci @fge pour expliquer .matches(). Peut-être savez-vous pourquoi .find()fonctionne si lentement dans cet exemple ?
Konstantin Konopko

3
Qu'entendez-vous par d' autres langues qui ont emboîté le pas ? D'après ce que je sais, seul C ++ a un ensemble équivalent de méthodes - regex_searchet regex_match. En Python, re.matchancre uniquement la correspondance au début de la chaîne (comme si c'était le cas \Apattern) et Python 3.x a une .fullmatch()méthode intéressante . Dans JS, Go, PHP et .NET, il n'y a pas de méthodes regex qui ancrent implicitement la correspondance. Les modèles ElasticSearch, XML Schema et HTML5 / Validators Angluar sont toujours ancrés par défaut. Dans Swift / Objective C, il existe un moyen d'ancrer le motif au début avec une option.
Wiktor Stribiżew

Existe-t-il un moyen de le faire en ligne?
Cardinal - Réintégrer Monica le

44

[a-z]correspond à un seul caractère entre a et z. Donc, si votre chaîne était juste "d", par exemple, elle aurait correspondu et aurait été imprimée.

Vous devez changer votre expression régulière pour [a-z]+qu'elle corresponde à un ou plusieurs caractères.


12
Bien sûr, cela correspond à un seul caractère, c'est ce que fait cette expression rationnelle! Ce qui n'est pas clair cependant (et ne devrait pas être le cas non plus!), C'est que java met le préfixe ^et le suffixe $autour de l'expression rationnelle fournie, la modifiant de manière indésirable et créant des bogues étranges. Ils ne devraient pas faire cela, car ce n'est pas ainsi que l'expression rationnelle initiale était conçue.
klaar

28

String.matchesrenvoie si la chaîne entière correspond à l'expression régulière, et non à n'importe quelle sous-chaîne.


3
Ce qui est vraiment une triste réalité, c'est que vous avez raison. Je ne sais vraiment pas pourquoi ils l'ont fait de cette façon.
Hola Soy Edu Feliz Navidad

16

L'implémentation java des expressions régulières essaie de faire correspondre la chaîne entière

c'est différent des expressions rationnelles perl, qui essaient de trouver une partie correspondante

si vous voulez trouver une chaîne avec rien d'autre que des minuscules, utilisez le modèle [a-z]+

si vous voulez trouver une chaîne contenant au moins un caractère minuscule, utilisez le modèle .*[a-z].*


plus d'infos ici
ycomp

3
Pourquoi n'est-ce pas documenté ?!
Leo Orientis

12

Utilisé

String[] words = {"{apf","hum_","dkoe","12f"};
    for(String s:words)
    {
        if(s.matches("[a-z]+"))
        {
            System.out.println(s);
        }
    }

4

J'ai rencontré le même problème une fois:

Pattern ptr = Pattern.compile("^[a-zA-Z][\\']?[a-zA-Z\\s]+$");

Ce qui précède a échoué!

Pattern ptr = Pattern.compile("(^[a-zA-Z][\\']?[a-zA-Z\\s]+$)");

Ce qui précède a fonctionné avec un motif à l'intérieur (et ).


2

Votre expression régulière [a-z]ne correspond pas dkoecar elle ne correspond qu'aux chaînes de longueur 1. Utilisez quelque chose comme [a-z]+.


-1

vous devez mettre au moins une capture ()dans le motif pour correspondre, et corriger le motif comme ceci:

String[] words = {"{apf","hum_","dkoe","12f"};
for(String s:words)
{
    if(s.matches("(^[a-z]+$)"))
    {
        System.out.println(s);
    }
}

Les crochets n'ont rien changé.
Touniouk

@Touniouk sans crochets matchesn'a aucune sortie.
MohsenB

-3

Vous pouvez rendre votre modèle insensible à la casse en faisant:

Pattern p = Pattern.compile("[a-z]+", Pattern.CASE_INSENSITIVE);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.