Direktes Suchen und Ersetzen

(Auszug aus "Reguläre Ausdrücke" von Jeffrey E. F. Friedl)

Bisher haben wir java.util.regex nur auf String-Objekte angewandt. Weil ein Matcher für jedes Objekt erzeugt werden kann, das das Interface CharSequence implementiert, kann man Texte auch direkt manipulieren.

Die dafür üblichen Klassen sind StringBuffer und StringBuilder, wobei die erste die weniger effiziente, dafür aber Thread-sichere Version ist. Beide können anstelle von String-Objekten verwendet werden, aber zusätzlich können sie direkt modifiziert werden. In den Beispielen in diesem Buch wird StringBuilder verwendet, man kann aber ebenso gut StringBuffer nehmen, wenn man mit einer Multithread-Umgebung arbeitet.

Im folgenden Beispiel werden in einem StringBuilder-Objekt Wörter, die ausschließlich aus Großbuchstaben bestehen, durch die entsprechenden Wörter in Kleinbuchstaben ersetzt: (Anmerkung: Die Regex in diesem Programmbeispiel ist ˹\b[\p{Lu}\p{Lt}]+\b˼. Wie wir unter Features und Dialekte gesehen haben, passt \p{Lu} auf alle Unicode-Großbuchstaben und \p{Lt} passt auf alle Buchstaben in Titelschreibweise. Die ASCII-Version dieser Regex wäre ˹\b[A-Z]+\b˼.)

StringBuilder text = new StringBuilder("Hör ENDLICH auf RUMZUBRÜLLEN!");
Matcher m = Pattern.compile("\\b[\\p{Lu}\\p{Lt}]+\\b").matcher(text);
while (m.find())
   text.replace(m.start(), m.end(), m.group().toLowerCase());
System.out.println(text);

Das Programmstück gibt folgenden Text aus:

Hör endlich auf rumzubrüllen!

Aus den zwei Treffern ergeben sich zwei Aufrufe von text.replace. Mit den ersten zwei Parametern wird der Bereich der zu ersetzenden Zeichen angegeben (das sind einfach Anfang und Ende des Treffers) und mit dem dritten der einzufügende Text (die Kleinbuchstaben-Version des Treffers).

Solange – wie hier – der Ersatztext genau so lang wie der Treffer ist, ist dieses direkte Suchen und Ersetzen sehr einfach. Wenn iterativ immer nur der erste Treffer ersetzt wird, bleibt der Code ebenso einfach.

Ersetzen mit einem Ersatztext anderer Länge

Die Verarbeitung wird komplizierter, wenn der Ersatztext eine andere Länge aufweist als der Treffertext. Wenn sich der Suchtext »unter der Hand« verändert, kann sich die aktuelle Position verschieben.

Wir können das Problem lösen, indem wir selbst einen expliziten Zeiger auf die aktuelle Position verwalten und ihn jeweils der find-Methode als Startwert übergeben. Im folgenden Beispiel wird der Ersatztext durch <b>...</b> eingeklammert.

StringBuilder text = new StringBuilder("Hör ENDLICH auf RUMZUBRÜLLEN!");
Matcher m = Pattern.compile("\\b[\\p{Lu}\\p{Lt}]+\\b").matcher(text); 
int matchZeiger = 0;      // Die erste Suche beginnt am Anfang des Strings.
while (m.find(matchZeiger)) {
   matchZeiger = m.end(); // Die nächste beginnt, wo die vorherige aufgehört hat.
   text.replace(m.start(), m.end(), "<b>"+ m.group().toLowerCase() +"</b>");
   matchZeiger += 7;      // Zusätzliche 7 Zeichen (fl<b>fl und fl</b>fl).
}
System.out.println(text);

Das ergibt:

Hör <b>endlich</b> auf <b>rumzubrüllen</b>!

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema Reguläre Ausdrücke bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:
   

Copyright der deutschen Ausgabe © 2008 by O’Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "Reguläre Ausdrücke" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstr. 81, 50670 Köln