2010-10-15 8 views
23

Ich verwende eine while(matcher.find()), um durch alle Übereinstimmungen eines Musters zu durchlaufen. Für jede gefundene Instanz oder Übereinstimmung dieses Musters möchte ich matcher.group(3) durch etwas neuen Text ersetzen. Dieser Text wird für jeden anders sein, also verwende ich matcher.appendReplacement(), um die ursprüngliche Zeichenfolge mit den neuen Änderungen neu zu erstellen, während es durchgeht. appendReplacement() ersetzt jedoch das gesamte Muster anstelle nur der Gruppe.Wie kann man Replacement in einer Matcher-Gruppe anstelle des gesamten Musters anhängen?

Wie kann ich das tun, aber nur die dritte Gruppe der Übereinstimmung und nicht das gesamte Muster ändern? Hier

ist einige Beispiel-Code:

Pattern pattern = Pattern.compile("THE (REGEX) (EXPRESSION) (WITH MULTIPLE) GROUPS"); 
Matcher matcher = pattern.matcher("THE TEXT TO SEARCH AND MODIFY"); 
StringBuffer buffer = new StringBuffer(); 

while(matcher.find()){ 
    matcher.appendReplacement(buffer, processTheGroup(matcher.group(3)); 
} 

aber ich möchte so etwas tun (natürlich funktioniert dies nicht).

... 
while(matcher.find()){ 
    matcher.group(3).appendReplacement(buffer, processTheGroup(matcher.group(3)); 
} 

So etwas, wo es nur eine bestimmte Gruppe ersetzt, nicht das ganze Muster.

BEARBEITEN: Das Regex-Beispiel wurde geändert, um anzuzeigen, dass nicht alle Muster gruppiert sind.

Antwort

16

Nehmen wir an, Ihr gesamtes Muster entspricht "(prefix)(infix)(suffix)" und fängt die 3 Teile in die Gruppen 1, 2 und 3 ein. Nehmen wir an, Sie möchten nur die Gruppe 2 (das Infix) ersetzen und das Präfix und Suffix unverändert lassen.

Dann, was Sie tun, ist man anfügen, was group(1) angepasst (unverändert), den neuen Ersatz für group(2) und welche group(3) angepasst (unverändert), so etwas wie diese:

matcher.appendReplacement(
    buffer, 
    matcher.group(1) + processTheGroup(matcher.group(2)) + matcher.group(3) 
); 

Dies wird noch passen und ersetzen das gesamte Muster, aber da die Gruppen 1 und 3 unberührt bleiben, wird effektiv nur das Infix ersetzt.

Sie sollten die gleiche grundlegende Technik für Ihr spezielles Szenario anpassen können.

+0

Das ist großartig danke. Gibt es auch eine Möglichkeit, dies zu tun, wenn einige Aspekte des Musters nicht in Gruppen sind? (Ich habe das Beispiel meines ursprünglichen Posts bearbeitet.) – cottonBallPaws

+1

Wenn Sie diese Teile in das Match aufnehmen müssen (dh Sie können sie nicht aus dem Muster entfernen), dann möchten Sie sie in einer Gruppe erfassen, damit Sie sich daran erinnern können, was sie gefunden haben und legen Sie sie unverändert als Teil Ihres Ersatzes zurück. – polygenelubricants

+0

Beachten Sie, dass dies fehlschlägt, wenn eine der übereinstimmenden Zeichenfolgen ein '$' enthält. Siehe Warrens Antwort unten. – Mene

27

Ich sehe dies bereits eine akzeptierte Antwort, aber es ist nicht völlig richtig. Die richtige Antwort scheint so etwas zu sein:

.appendReplacement("$1" + process(m.group(2)) + "$3"); 

Dies zeigt auch, dass „$“ ist ein Sonderzeichen in .appendReplacement. Daher müssen Sie in Ihrer Funktion "process()" darauf achten, dass alle "$" durch "\ $" ersetzt werden. Matcher.quoteReplacement (replacementString) wird dies für Sie tun (danke @Med)

Die vorherige akzeptierte Antwort schlägt fehl, wenn entweder Gruppen 1 oder 3 ein "$" enthalten. Sie werden am Ende mit "java.lang.IllegalArgumentException: Illegal Gruppenreferenz"

+10

Um dieses '$' Problem zu lösen, macht 'Matcher.quoteReplacement (replacementString) 'den Trick. – Med