Regex funktioniert nicht in String.matches ()

147

Ich habe diesen kleinen Code

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

Soll drucken

dkoe

aber es druckt nichts !!

John
quelle
41
Java matchessetzt für Sie ein ^ am Anfang und ein $ am Ende der regulären Ausdrücke. Also matches("[a-z]")wird stattdessen tatsächlich nach / ^ [az] $ / gesucht.
Robino
Ja @Robino du hast absolut recht.
Mihir
1
Wenn Sie erwarten matches, nach einem Vorkommen von zu suchen , sollte es sicherlich zu [a-z]allen passen? Ich würde nicht erwarten matches, jedes einzelne Zeichen einzeln mit dem regulären Ausdruck zu vergleichen.
PhilHibbs
@Robino: Wo wird diese Funktionalität beschrieben / dokumentiert?
Toru
@Toru Auf der Java-Dokumentenseite für String.Matches - wo sonst? Ein gelegentliches Google von "Java-String stimmt mit Dokumentation überein" zeigt im oberen Ergebnis, dass der Ausdruck "str.matches (Regex) genau das gleiche Ergebnis wie der Ausdruck liefert". Das wichtige Wort ist "genau".
Robino

Antworten:

323

Willkommen bei Javas falsch benannter .matches()Methode ... Sie versucht und stimmt mit ALLEN Eingaben überein. Leider sind andere Sprachen gefolgt :(

Wenn Sie sehen möchten, ob der reguläre Ausdruck mit einem Eingabetext übereinstimmt, verwenden Sie a Pattern, a Matcherund die .find()Methode des Matchers:

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

Wenn Sie in der Tat sehen möchten, ob eine Eingabe nur Kleinbuchstaben enthält, können Sie sie verwenden .matches(), aber Sie müssen ein oder mehrere Zeichen abgleichen: Fügen Sie a +wie in Ihrer Zeichenklasse hinzu, wie in [a-z]+. Oder verwenden Sie ^[a-z]+$und .find().

fge
quelle
2
Ich finde Hunderte von unvollständigen Tutorials online. Konnte keinen guten finden. Hast du irgendwelche Vorschläge?
John
Vielen Dank an @fge für die Erklärung .matches(). Vielleicht wissen Sie, warum .find()in diesem Beispiel so langsam funktioniert ?
Konstantin Konopko
3
Was meinst du mit anderen Sprachen ? Soweit ich weiß, verfügt nur C ++ über einen entsprechenden Satz von Methoden - regex_searchund regex_match. In Python wird re.matchdie Übereinstimmung nur am Anfang des Strings verankert (als wäre es so \Apattern), und Python 3.x hat eine nette .fullmatch()Methode. In JS, Go, PHP und .NET gibt es keine Regex-Methoden, die die Übereinstimmung implizit verankern. ElasticSearch-, XML-Schema- und HTML5 / Validators-Angluar-Muster sind standardmäßig immer verankert. In Swift / Objective C gibt es eine Möglichkeit, das Muster am Anfang mit einer Option zu verankern.
Wiktor Stribiżew
Gibt es einen Oneliner-Weg, um dies zu tun?
Kardinal - Wiedereinsetzung Monica
44

[a-z]stimmt mit einem einzelnen Zeichen zwischen a und z überein . Wenn Ihre Zeichenfolge "d"beispielsweise nur wäre, wäre sie übereinstimmend und ausgedruckt worden.

Sie müssen Ihre Regex so ändern, dass [a-z]+sie mit einem oder mehreren Zeichen übereinstimmt.

Dogbane
quelle
12
Natürlich passt es zu einem einzelnen Zeichen, genau das macht dieser reguläre Ausdruck! Was jedoch nicht klar ist (und auch nicht der Fall sein sollte!), Ist, dass Java das Präfix ^und Suffix $um den bereitgestellten regulären Ausdruck setzt, es unerwünscht ändert und seltsame Fehler erzeugt. Sie sollten das nicht tun, denn so war der ursprüngliche reguläre Ausdruck nicht gemeint.
Klaar
28

String.matchesGibt zurück, ob die gesamte Zeichenfolge mit dem regulären Ausdruck übereinstimmt, nicht mit einer beliebigen Teilzeichenfolge.

yshavit
quelle
3
Was wirklich traurig ist, ist, dass Sie Recht haben. Ich weiß wirklich nicht, warum sie es so gemacht haben.
Hola Soja Edu Feliz Navidad
16

Die Implementierung von Regexes in Java versucht, mit der gesamten Zeichenfolge übereinzustimmen

Das unterscheidet sich von Perl-Regexen, die versuchen, ein passendes Teil zu finden

Wenn Sie eine Zeichenfolge mit nur Kleinbuchstaben suchen möchten, verwenden Sie das Muster [a-z]+

Wenn Sie eine Zeichenfolge suchen möchten, die mindestens ein Kleinbuchstaben enthält, verwenden Sie das Muster .*[a-z].*

Hachi
quelle
Weitere Infos hier
ycomp
3
Warum ist das nicht dokumentiert ?!
Leo Orientis
12

Gebraucht

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

Ich habe einmal das gleiche Problem gehabt:

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

Das obige ist fehlgeschlagen!

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

Das obige arbeitete mit Muster innerhalb (und ).

Shanta
quelle
2

Ihr regulärer Ausdruck [a-z]stimmt nicht überein, dkoeda er nur mit Zeichenfolgen der Länge 1 übereinstimmt. Verwenden Sie so etwas wie [a-z]+.


quelle
-1

Sie müssen mindestens eine Aufnahme ()in das passende Muster einfügen und das Muster wie folgt korrigieren:

String[] words = {"{apf","hum_","dkoe","12f"};
for(String s:words)
{
    if(s.matches("(^[a-z]+$)"))
    {
        System.out.println(s);
    }
}
MohsenB
quelle
Klammern haben nichts geändert.
Touniouk
@Touniouk ohne Klammern matcheshaben keine Ausgabe.
MohsenB
-3

Sie können die Groß- und Kleinschreibung Ihres Musters nicht berücksichtigen, indem Sie Folgendes tun:

Pattern p = Pattern.compile("[a-z]+", Pattern.CASE_INSENSITIVE);
Anita Kulkarni
quelle