5 Stimmen

Regexp Gruppierung und replaceAll mit .* in Java dupliziert die Ersetzung

Ich habe ein Problem mit Rexexp in Java. Der Beispielcode schreibt aus ABC_012_suffix_suffix Ich hatte erwartet, dass er Folgendes ausgibt ABC_012_suffix

    Pattern rexexp  = Pattern.compile("(.*)");
    Matcher matcher = rexexp.matcher("ABC_012");
    String  result  = matcher.replaceAll("$1_suffix");

    System.out.println(result);

Ich verstehe, dass replaceAll alle übereinstimmenden Gruppen ersetzt, die Fragen ist, warum ist diese Regexp-Gruppe (.*) zweimal auf meine Zeichenfolge passen ABC_012 in Java?

6voto

Andreas Dolk Punkte 110776
Pattern regexp  = Pattern.compile(".*");
Matcher matcher = regexp.matcher("ABC_012");
matcher.matches();
System.out.println(matcher.group(0));
System.out.println(matcher.replaceAll("$0_suffix"));

Das Gleiche passiert hier, die Ausgabe ist:

ABC_012
ABC_012_suffix_suffix

Der Grund dafür liegt in der replaceAll Methode: Sie versucht, die find alle Teilsequenzen, die dem Muster entsprechen:

while (matcher.find()) {
  System.out.printf("Start: %s, End: %s%n", matcher.start(), matcher.end());
}

Dies führt zu:

Start: 0, End: 7
Start: 7, End: 7

Zu unserer ersten Überraschung hat der Matcher findet zwei Teilsequenzen, "ABC_012" und eine weitere "" . Und er fügt hinzu "_suffix" für beide:

"ABC_012" + "_suffix" + "" + "_suffix"

0 Stimmen

Eine sehr gute Analyse. Sie ist laut Regexp korrekt, da .* auch auf "" passt. Allerdings ist das sehr verwirrend :-)

5voto

Alex Nikolaenkov Punkte 2477

Wahrscheinlich .* gibt Ihnen "volle Übereinstimmung" und reduziert dann die Übereinstimmung auf "leere Übereinstimmung" (aber immer noch eine Übereinstimmung). Versuchen Sie (.+) o (^.*$) stattdessen. Beide funktionieren wie erwartet.

Bei regexinfo ist star wie folgt definiert:

*(Stern) - Wiederholt das vorherige Element null oder mehr Mal. Gierig, d. h. es werden so viele Elemente wie möglich abgeglichen, bevor Permutationen mit weniger Übereinstimmungen des vorhergehenden Elements versucht werden, bis zu dem Punkt, an dem das vorhergehende Element überhaupt nicht mehr abgeglichen wird.

3voto

Richard H Punkte 36131

Wenn Sie nur "_suffix" zu Ihrer Eingabe hinzufügen wollen, warum tun Sie es nicht einfach:

String result = "ABC_012" + "_suffix";

?

0 Stimmen

(Ich schätze, das war nicht die Frage - die rätselhafte Frage war, warum wir ein zusätzliches _suffix zum Ergebnis hinzugefügt haben)

0 Stimmen

@Andreas_D: wahr, aber es gibt das richtige Ergebnis ohne komplizierte Dinge mit unnötigen Regexes. Ich versuche nur, es einfach zu halten :)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X