Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 5. Auflage
 <<    <     >    >>   API  Kapitel 17 - Utility-Klassen II

17.1 Reguläre Ausdrücke



Seit der Version 1.4 enthält das JDK auch Klassen zur Verwendung von regulären Ausdrücken. Dabei handelt es sich um Muster, die Mengen von Zeichenketten beschreiben und stellvertretend für diese stehen.

Wenn Sie schon einmal die Datei-Suchfunktionalität Ihres Betriebssystems verwendet haben, haben Sie wahrscheinlich - ohne es zu bemerken - einen regulären Ausdruck verwendet. Um beispielsweise alle Dateien in einem Ordner aufzulisten, suchen Sie typischerweise mit dem Muster *.*. Dabei steht der Stern stellvertretend für eine beliebige Zeichenkette und schon haben Sie einen (wenn auch recht einfachen) regulären Ausdruck verwendet, um nicht jeden Dateinamen einzeln hinschreiben zu müssen.

17.1.1 Die Klasse Pattern

Um einen regulären Ausdruck zu erzeugen, hält das JDK die Klasse Pattern im Package java.util.regex bereit. So ist a*b beispielsweise ein Pattern zur Beschreibung der Zeichenketten b, ab, aab und so weiter. Wobei der Stern - wie allgemein üblich - für eine beliebige Menge von Zeichen steht. Der obige Ausdruck ließt sich also: »Eine beliebige Anzahl von kleinen as, gefolgt von einem b«.

Die folgende Tabelle zeigt einige häufig verwendete Platzhalter. Die Möglichkeiten regulärer Ausdrücke in Java sind dabei so vielfältig, dass Sie allein ein ganzes Kapitel füllen würden. Eine vollständige Liste findet man z.B. in den JavaDocs zur Klasse Pattern.

Symbol Bedeutung
. Ein beliebiges einzelnes Zeichen
* Eine beliebige Menge von Zeichen
\d Eine Zahl zwischen 0 und 9
\D Ein Zeichen das keine Zahl darstellt.
\s Ein beliebiges Leerzeichen (Whitespace)
\S Ein Zeichen, das kein Leerzeichen ist

Tabelle 17.1: Häufige Elemente für reguläre Ausdrücke in Java

Achten Sie bei der Programmierung von regulären Ausdrücken darauf, dass das Baskslash-Zeichen (\) in Strings reserviert ist und durch einen doppelten Backslash (\\) kodiert werden muss.

 Warnung 

17.1.2 Die Klasse Matcher

Während die Klasse Pattern einen regulären Ausdruck repräsentiert, können Sie mit Hilfe der Methode matcher ein Matcher-Objekt erzeugen, das verwendet werden kann, um eine beliebige Zeichenkette auf den regulären Ausdruck zu testen.

Die Klassen für Pattern und Matcher sind dabei getrennt worden, da erstere auf der einen Seite relativ komplexe Objekte sind, auf der anderen allerdings auch threadsafe programmiert sind und in nebenläufigen Programmen von verschiedenen Threads gemeinsam genutzt werden können. Matcher auf der anderen Seite sind leichtgewichtige Objekte, die nur von einem Thread verwendet werden sollten. In einem Satz: Sie können jeden benötigten Ausdruck durch ein global zu verwendendes Pattern beschreiben und von diesem bei Bedarf beliebig viele Matcher-Objekte erzeugen lassen.

17.1.3 Vergleich einer Zeichenkette mit einem regulären Ausdruck

Neben der Möglichkeit, Zeichenketten untereinander auf (partielle) Gleichheit zu überprüfen, wie es in Abschnitt 11.2.4 beschrieben wird, kann mit Hilfe von regulären Ausdrücken auch überprüft werden, ob eine Zeichenkette von einem Ausdruck beschrieben wird. Hierzu erzeugt man zunächst ein Pattern-Objekt, das den Ausdruck repräsentiert und anschließend ein Matcher-Objekt, das zum Testen verwendet werden kann. Das folgende Listing verdeutlicht dies:

001 /* Listing1701.java */
002 
003 import java.util.regex.*;
004 
005 public class Listing1701
006 {
007   public static void main(String[] args)
008   {
009     // Erzeugen eines Pattern-Objektes für den Ausdruck a*b
010     Pattern p = Pattern.compile("a*b");
011 
012     // Erzeugen eines Matcher-Objektes für die Zeichenkette
013     Matcher m = p.matcher("aaaaab");
014 		
015     // Test, ob die Zeichenkette vom Ausdruck beschrieben wird
016     boolean b = m.matches();  
017   }
018 }
Listing1701.java
Listing 17.1: Reguläre Ausdrücke

Auffällig an diesem Listing ist, dass weder Pattern noch Matcher über einen Konstruktor erzeugt werden. Stattdessen verwenden wir die statische Methode compile, die ein Pattern- Objekt zurück gibt und die Methode matcher, um einen Matcher zu erzeugen. Der Grund liegt möglicherweise darin, dass das JDK die Pattern auf diese Weise intern cachen kann und auch bei der »zweiten« Kompilierung das gleiche Objekt zurückgibt - aber verlassen Sie sich nicht darauf.

Wie bereits weiter oben beschrieben lassen sich einmal erzeugte Pattern für viele Matcher wiederverwenden und helfen so, wertvolle Ressourcen zu sparen. Um nur eine einzige Zeichenkette auf ein Pattern zu testen, kann man aber auch die folgende Kurzform verwenden:

001 /* Listing1702.java */
002 
003 import java.util.regex.*;
004 
005 public class Listing1702
006 {
007   public static void main(String[] args)
008   {
009     // Testet die Zeichenkette auf das Pattern
010     boolean b = Pattern.matches("a*b", "aaaaab");
011   }
012 }
Listing1702.java
Listing 17.2: Kurzer Zeichenketten-Vergleich mit regulären Ausdrücken

Bei dieser Kurzversion wird das Pattern intern kompiliert, anschließend ein passender Matcher erzeugt und schließlich nur das Resultat zurückgegeben. Dieser »Einzeiler« ist zwar markant, allerdings lässt sich das Pattern nicht wiederverwenden.

Und es geht sogar noch kürzer und ohne explizite Verwendung der Klassen im Package java.util.regex, wie es das folgende Listing demonstriert. Seit dem JDK 5 stellt die Klasse String nämlich die Methode matches zur Verfügung, hinter der sich nichts anderes als oben beschriebene Kurzform verbirgt.

001 /* Listing1703.java */
002 
003 public class Listing1703
004 {
005   public static void main(String[] args)
006   {
007     // Testet die Zeichenkette auf das Pattern
008     boolean b = "aaaaab".matches("a*b");
009   }
010 }
Listing1703.java
Listing 17.3: Strings und reguläre Ausdrücke

17.1.4 Teilen einer Zeichenkette mit einem regulären Ausdruck

Neben dem Test auf Äquivalenz erlauben es reguläre Ausdrücke auch, Teile einer Zeichenkette zu ersetzen oder lange Zeichenketten in mehrere Teile aufzuspalten (engl. Splitting). Für letzteres besitzt die Klasse Pattern die Methoden split

public String[] split(CharSequence input)

public String[] split(CharSequence input, int limit)
java.util.regex.Pattern

Mit Hilfe des zweiten Parameters kann dabei angegeben werden, in wieviele Teile die Zeichenkette maximal aufgeteilt werden soll. Er ist eine Obergrenze für die Größe des zurückgegebenen Arrays. Wird als Limit eine negative Zahl angeben, wird die Zeichenkette beliebig oft durch das Pattern geteilt. Beide Methoden verhalten sich dann identisch.

Das folgende Listing zeigt das Splitting der Zeichenkette, die uns schon im Kapitel über Strings begegnet ist:

001 /* Listing1704.java */
002 
003 import java.util.regex.*;
004 
005 public class Listing1704
006 {
007   public static void main(String[] args)
008   {
009     // Der zu verwendende Testsatz
010     String satz = "Dies ist nur ein Test";
011     
012     // Jedes Whitespace-Zeichen soll zur 
013     // Trennung verwendet werden
014     Pattern p = Pattern.compile("\\s");
015     
016     // Verwendung der Methode split
017     String[] result = p.split(satz);
018     for (int x=0; x<result.length; x++) {
019       System.out.println(result[x]);
020     }
021   }
022 }
Listing1704.java
Listing 17.4: Zerlegen von Zeichenketten

Soll das Pattern nicht wiederverwendet werden, kann man auch in diesem Fall auf eine äquivalente Methode der Klasse String zurückgreifen, wie bereits in Abschnitt 11.2.7 beschrieben.


 Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 5. Auflage, Addison Wesley, Version 5.0.2
 <<    <     >    >>   API  © 1998, 2007 Guido Krüger & Thomas Stark, http://www.javabuch.de