Unterschied zwischen Übereinstimmungen () und find () in Java Regex

250

Ich versuche den Unterschied zwischen matches()und zu verstehen find().

Laut Javadoc wird ( matches()soweit ich weiß ) die gesamte Zeichenfolge durchsucht, auch wenn sie findet, wonach sie sucht, und sie find()wird aufhören, wenn sie findet, wonach sie sucht.

Wenn diese Annahme richtig ist, kann ich nicht sehen, wann Sie matches()stattdessen verwenden find()möchten, es sei denn, Sie möchten die Anzahl der gefundenen Übereinstimmungen zählen.

Meiner Meinung nach sollte die String-Klasse dann find()statt matches()als eingebaute Methode haben.

Um es zusammenzufassen:

  1. Ist meine Annahme richtig?
  2. Wann ist es sinnvoll, matches()statt zu verwenden find()?
Shervin Asgari
quelle
2
Beachten Sie, dass ein find()mehrmaliger Anruf unterschiedliche Ergebnisse für dasselbe Ergebnis liefern kann Matcher. Siehe meine Antwort unten.
L. Holanda

Antworten:

300

matchesversucht, den Ausdruck mit der gesamten Zeichenfolge abzugleichen und implizit ein ^am Anfang und $am Ende Ihres Musters hinzuzufügen , was bedeutet, dass nicht nach einer Teilzeichenfolge gesucht wird. Daher die Ausgabe dieses Codes:

public static void main(String[] args) throws ParseException {
    Pattern p = Pattern.compile("\\d\\d\\d");
    Matcher m = p.matcher("a123b");
    System.out.println(m.find());
    System.out.println(m.matches());

    p = Pattern.compile("^\\d\\d\\d$");
    m = p.matcher("123");
    System.out.println(m.find());
    System.out.println(m.matches());
}

/* output:
true
false
true
true
*/

123ist eine Teilzeichenfolge von, a123bsodass die find()Methode true ausgibt. matches()nur "sieht", a123bwas nicht dasselbe ist 123und somit false ausgibt.

Sanjay T. Sharma
quelle
25
Diese Antwort ist irreführend. matchers()ist nicht einfach ein find()mit impliziter Umgebung ^ und $. Beachten Sie, dass Aufruf .find()mehr als einmal unterschiedliche Ergebnisse haben kann , wenn nicht durch vorausgegangen reset(), während matches()immer gleiches Ergebnis zurück. Siehe meine Antwort unten.
L. Holanda
80

matchesGeben Sie true zurück, wenn die gesamte Zeichenfolge mit dem angegebenen Muster übereinstimmt. findversucht, einen Teilstring zu finden, der dem Muster entspricht.

Khachik
quelle
35
Man könnte sagen, das matches(p)ist das Gleiche, als find("^" + p + "$")ob das klarer wäre.
Jensgramm
4
Nur ein Beispiel zur Verdeutlichung der Antwort: "[az] +" mit der Zeichenfolge "123abc123" schlägt mit match () fehl, mit find () jedoch erfolgreich.
Bezmax
3
@ Max Genau, "123abc123".matches("[a-z]+")wird genauso scheitern wie "123abc123".find("^[a-z]+$")würde. Mein Punkt war, dass dies matches()für ein komplettes Match gilt, genau wie find()bei Start- und Endankern.
Jensgramm
5
Pattern.compile("some pattern").matcher(str).matches()ist gleichPattern.compile("^some pattern$").matcher(str).find()
AlexR
3
@AlexR / @jensgram: ...("some pattern").matcher(str).matches()ist nicht genau gleich, ...("^some pattern$").matcher(str).find()das gilt nur für den ersten Aufruf. Siehe meine Antwort unten.
L. Holanda
62

matches()gibt nur dann true zurück, wenn die vollständige Zeichenfolge übereinstimmt. find()wird versuchen, das nächste Vorkommen in der Teilzeichenfolge zu finden, das dem regulären Ausdruck entspricht. Beachten Sie die Betonung auf "das nächste". Das heißt, das Ergebnis eines find()mehrmaligen Anrufs ist möglicherweise nicht dasselbe. Darüber hinaus können find()Sie mithilfe von aufrufen start(), um die Position zurückzugeben, an der der Teilstring abgeglichen wurde.

final Matcher subMatcher = Pattern.compile("\\d+").matcher("skrf35kesruytfkwu4ty7sdfs");
System.out.println("Found: " + subMatcher.matches());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find());
System.out.println("Found: " + subMatcher.find());
System.out.println("Matched: " + subMatcher.matches());

System.out.println("-----------");
final Matcher fullMatcher = Pattern.compile("^\\w+$").matcher("skrf35kesruytfkwu4ty7sdfs");
System.out.println("Found: " + fullMatcher.find() + " - position " + fullMatcher.start());
System.out.println("Found: " + fullMatcher.find());
System.out.println("Found: " + fullMatcher.find());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());

Wird ausgegeben:

Gefunden: falsch
Gefunden: wahr - Position 4
Gefunden: wahr - Position 17
Gefunden: wahr - Position 20
Gefunden: falsch
Gefunden: falsch
Übereinstimmend: falsch
-----------
Gefunden: wahr - Position 0
Gefunden: falsch
Gefunden: falsch
Übereinstimmend: wahr
Übereinstimmend: wahr
Übereinstimmend: wahr
Übereinstimmend: wahr

Seien Sie also vorsichtig, wenn Sie find()mehrmals aufrufen, wenn das MatcherObjekt nicht zurückgesetzt wurde, auch wenn der reguläre Ausdruck von der vollständigen Zeichenfolge umgeben ist ^und $mit dieser übereinstimmt.

L. Holanda
quelle
2
sehr hilfreicher Kumpel
DockYard
6

find()wird die Unterzeichenfolge gegen den regulären Ausdruck betrachten, wobei as matches()den vollständigen Ausdruck berücksichtigt.

find() wird nur dann true zurückgeben, wenn die Unterzeichenfolge des Ausdrucks mit dem Muster übereinstimmt.

public static void main(String[] args) {
        Pattern p = Pattern.compile("\\d");
        String candidate = "Java123";
        Matcher m = p.matcher(candidate);

        if (m != null){
            System.out.println(m.find());//true
            System.out.println(m.matches());//false
        }
    }
Sumanth Varada
quelle
3

matches();find()puffert nicht, sondern puffert. find()Sucht zuerst bis zum Ende der Zeichenfolge, indiziert das Ergebnis und gibt den Booleschen Wert und den entsprechenden Index zurück.

Deshalb, wenn Sie einen Code wie haben

1:Pattern.compile("[a-z]");

2:Pattern.matcher("0a1b1c3d4");

3:int count = 0;

4:while(matcher.find()){

5:count++: }

Bei 4: Die Regex-Engine, die die Musterstruktur verwendet, liest den gesamten Code durch (Index zu Index, wie durch angegeben regex[single character], um mindestens eine Übereinstimmung zu finden. Wenn eine solche Übereinstimmung gefunden wird, wird sie indiziert, und die Schleife wird basierend auf ausgeführt Das indizierte Ergebnis sonst, wenn es keine Vorausberechnung wie die folgende durchführt matches(), funktioniert nicht. Die while-Anweisung würde niemals ausgeführt, da das erste Zeichen der übereinstimmenden Zeichenfolge kein Alphabet ist.


quelle