Die Community zu .NET und Classic VB.
Menü

Reguläre Ausdrücke

 von 

Übersicht 

Die folgende Kolumne bietet eine Einführung in die Welt der Regulären Ausdrücke, die ein sehr mächtiges Werkzeug in der Bearbeitung von Strings bilden. Die Kolumne war ursprünglich auf Perl bezogen und wurde leicht umgeschrieben, um neben einer allgemeinen Einführung auch die Mechanismen in VB Classic und VB.NET aufzuzeigen, die benötigt werden, um reguläre Ausdrücke zu nutzen.

Mit freundlichen Grüßen,
Colin Schlüter

1. Überblick  

1.1 Was sind Reguläre Ausdrücke?

Eine der nützlichsten Eigenschaften von Perl (wenn nicht die nützlichste Eigenschaft) ist das mächtige String-Handling. Reguläre Ausdrücke oder Regular Expressions sind dabei eines der mächtigsten Werkzeuge in Perl und mittlerweile auch einigen anderen Programmiersprachen, so VB.NET.
Damit können bestimmte Muster in einem Text gesucht und auch ersetzt werden. Zum Beispiel kann man mit einfachen Mitteln testen, ob ein String wie eine Email-Adresse aussieht. Reguläre Ausdrücke können auch als komplexe Suchausdrücke verwendet werden und um große Datenbestände zu durchsuchen.

Reguläre Ausdrücke sind allerdings für Neulinge, die nicht aus der Unix-Welt kommen, sehr ungewohnt und einer der Hauptgründe dafür, warum in manchen Perl-Scripts ziemlich merkwürdige, kryptisch anmutende Zeichenfolgen vorkommen. Trotzdem lässt sich das Grundprinzip relativ einfach verstehen und zur Erleichterung der Programmierarbeit einsetzen.

1.2 Anwendungsbeispiele

Reguläre Ausdrücke sind an vielen Stellen in der Programmierung sinnvoll und können dem Programmierer dabei die Arbeit stark erleichtern, den Quellcode kürzer und übersichtlicher machen. Angewendet werden reguläre Ausdrücke zum Beispiel

  • zur Überprüfung von Benutzereingaben (Email-Adressen, URLs, Adressen, Benutzernamen, Datumseingaben, etc.),
  • zur Verarbeitung von String-Daten (Systemzeit, Datei-Lese-Vorgänge, etc.),
  • zum Suchen und Ersetzen innerhalb von Texten,
  • zum Zerlegen von Strings nach vorgegebenen Mustern,
  • zum Parsen von Texten
  • ...

2. Aufbau regulärer Ausdrücke  

Ein regulärer Ausdruck ist allgemein ein Muster (engl. Pattern), das mit dem zu untersuchenden String verglichen und auf Übereinstimmungen (Matches) überprüft wird.

2.1 Zeichen/Zeichenfolgen/Zeichenklassen

Beginnen wir mit einem einfachen Beispiel, der Überprüfung, ob ein String den Buchstaben "b" enthält. Der entsprechende reguläre Ausdruck dazu sieht folgendermaßen aus:

b

Was bedeutet dies nun genau? Die RegEx-Maschine durchsucht einen String von links nach rechts und überprüft, ob der Buchstabe "b" auftritt.

Der Ausdruck passt (matcht) also auf "Buchstabe" oder "bla bla bla", aber nicht auf "Zahl" oder "Buch" (Groß-/Kleinschreibung wird unterschieden!).

Genauso lässt sich auch das Auftreten einer Zeichenfolge testen:

test

passt zum Beispiel auf "getestet" und "testen".

Eine weitere Möglichkeit, das Auftreten von Buchstaben zu überprüfen sind sogenannte Zeichenklassen. Dabei kann man eine Gruppe von Zeichen zusammenstellen, die alternativ vorkommen können.

[abc]

passt dementsprechend auf jeden String, der entweder ein a, b, oder c enthält. Die gesamte Klammer stellt also nur ein Zeichen im Suchmuster dar.
Dieses Verfahren lässt sich auch genau umgekehrt verwenden:

[^abc]

steht für ein beliebiges Zeichen außer a, b und c.

Außerdem lassen sich in Zeichenklassen auch Bereiche angeben:

[a-z]

matcht also einen beliebigen Kleinbuchstaben.

2.2 Platzhalter und Steuerzeichen

In vielen Fällen, kann oder will man allerdings die zu findenden Zeichen nicht so genau angeben, sondern auch beliebige Zeichen erlauben. Dazu existiert in regulären Ausdrücken der Punkt . als Metazeichen, das standardmäßig alle Zeichen außer dem Zeilenumbruch findet.

a.

passt also auf "an" oder "ab" etc.

Oftmals möchte man aber nicht unbedingt alle Zeichen erlauben, sondern nur Buchstaben oder nur Zahlen. Auch dafür gibt es in regulären Ausdrücken Kurzformen:

String Bedeutung Erklärung
\d digit Ziffern 0 bis 9
\D   Jedes Zeichen außer 0 bis 9
\w word Wort-Zeichen sind Buchstaben, Zahlen und der Unterstrich _
\W   Alles außer den Zeichen von \w
\s space Leerzeichen, Tabulatoren oder Zeilenumbruch
\S   alles außer \s

Tabelle 2. 1 : Spezielle Zeichenklassen

\d

matcht zum Beispiel eine beliebige Zahl.

2.3 Klammern und Alternativen

Grundsätzlich können in regulären Ausdrücken runde Klammern gesetzt werden, um bestimmte Abschnitte zusammenzufassen. Besonders hilfreich ist das, um Alternativmöglichkeiten anzugeben. Diese werden in Klammern gesetzt und durch einen senkrechten Strich (Pipe) | getrennt:

(ab|an)geben

matcht z.B. "angeben" und "abgeben".

2.4 Quantifiers (Wiederholungsoperatoren)

Zeichenwiederholungen können in regulären Ausdrücken mit Wiederholungsoperatoren gekennzeichnet werden.
Das Fragezeichen ? bedeutet: das Zeichen vor dem Fragezeichen oder auch nicht.

aus?

matcht also "aus" und "au".

Das Pluszeichen + bedeutet: eine oder mehrere Wiederholungen des Zeichens, das vor dem Pluszeichen steht.

aus+

matcht also "aus", "auss", "ausss", etc.

Das Sternzeichen * bedeutet: keine, eine oder mehrere Wiederholungen des Zeichens, das vor dem Sternzeichen steht.

aus*

matcht also "au", "aus", "auss", etc.

Wenn vor den Zeichen + oder * ein Punkt . steht (der für ein fast beliebiges Zeichen steht), erzeugt man einen Platzhalter, der dem *-Platzhalter in der DOS/Windows-Welt, etwa bei Dateinamen, oder auch bei der Google-Suche entspricht:

aus.*

findet "aus", "ausgeben", "ausgehen", "ausfahrbar" etc.

Geschweifte Klammern mit einer Zahl oder zwei durch Komma getrennten Zahlen darin stehen für Wiederholungen des Zeichens vor der geschweiften Klammer an der betreffenden Stelle. Dabei können Sie auch das Punktzeichen vor der geschweiften Klammer notieren. In diesem Fall bedeutet die Angabe innerhalb der geschweiften Klammer: so viele beliebige Zeichen wie angegeben.

Die erste Zahl in den Klammern bedeutet dabei die Mindest-, die zweite die Höchst-Anzahl an Zeichen.

x{3,6}

matcht zwischen 3 und 6mal "x".

Wird eine der beiden Zahlen weggelassen, so gilt entsprechen nur eine Mindest- bzw. Höchstzahl, also

x{3,}

für 3 und mehr "x" bzw.

x{,5}

für 0 bis 5 "x".

Wird nur eine Zahl ohne Komma notiert, so gilt diese als genaue Anzahl an Zeichen:

x{7}

matcht genau 7mal "x".

Alle der aufgeführten Quantifiers (Wiederholungsoperatoren) gelten dabei nicht nur für einzelne Zeichen, wie in den bisherigen Beispielen, sondern lassen sich auch auf geklammerte Zeichenklassen oder Teile des regulären Ausdrucks anwenden.

(abc)+

matcht z.B. "abc", "abcabc", "abcabcabc" etc. und

(a.){2,3}

matcht 2- bis 3mal ein "a" gefolgt von einem beliebigen Zeichen, also z.B. "axax" oder "a-a-a-".

2.5 Anfang/Ende

In regulären Ausdrücken gibt es auch spezielle Zeichen, die Zeilen- bzw. String-Anfang und -Ende kennzeichnen. Das Caret-Zeichen ^ steht dabei für den Zeilenanfang, das Dollarzeichen $ für das Zeilenende.

^abc

matcht also die Zeichenkette "abc", aber nur wenn diese am Anfang des untersuchten Strings steht,

abc$

matcht "abc" nur am Ende des untersuchten Strings.

2.6 Metazeichen

Alle bis jetzt genannten Zeichen, also . ? + * ^ $ \ ( ) [ ] { } haben spezielle Bedeutungen in regulären Ausdrücken. Um diese Zeichen im Text zu finden, müssen sie daher mit einem Backslash \ gekennzeichnet werden:

\.

matcht einen Punkt (und kein beliebiges Zeichen).

3. Reguläre Ausdrücke in VB  

Wie in vielen andere Sprachen auch, sind reguläre Ausdrücke in VB Classic kein fester Bestandteil der Sprache an sich (wie dies z.B. bei Perl der Fall ist). Um reguläre Ausdrücke zu verwenden, muss man zunächst eine Bibliothek bemühen, in diesem Fall die Scripting Dll, deren Benutzung man sich aber gut überlegen sollte, da die Scripting Runtime diverse Nachteile mit sich bringt und auf vielen PCs daher nicht installiert ist. Alternativ gibt es natürlich auch einige RegExp-Bibliotheken im Internet, wie Google zutage fördert.

In VB.NET hingegen braucht meine keine extra Bibliothek, da reguläre Ausdrücke fester Bestandteil des Frameworks sind und im Namespace System.Text.RegularExpressions zu finden. Im Grunde funktionieren sie recht ähnlich wie die Klasse aus der Scripting Dll.

3.1 VB Classic

Im Folgenden sei kurz vorgestellt, wie man in VB Classic mit Hilfe der regulären Ausdrücke Text sucht und ersetzt. Als erstes muß dazu der Verweis Microsoft VBScript Regular Expressions 5.0 gesetzt werden (die Version kann variieren). Nun ist die Klasse benutzbar.

Private Sub Command1_Click()
    Dim TestString As String
    
    With New RegExp
        .Pattern = "^http://[a-z]+[-a-z]+(\.[a-z]+)?$"
        .IgnoreCase = True
        
        TestString = "http://colinschlueter.de"
        
        If .Test(TestString) Then
            Call MsgBox(TestString & " ist eine gültige URL")
        Else
            Call MsgBox(TestString & " ist keine gültige URL")
        End If
    End With
End Sub

Listing 3.1

Dieses Beispiel zeigt, wie man einen String mit einem Suchpattern vergleichen kann. Im Prinzip ist das ähnlich wie mit dem VB-Operator Like, jedoch um Längen mächtiger. Die Funktion der regulären Ausdrücke beschränkt sich jedoch nicht auf diese Funktion.

Private Sub Command2_Click()
    Dim TestString As String
    
    With New RegExp
        .Pattern = "\s+(\w)"
        .Global = True
        
        TestString = "Ich  weiß   nicht, was  soll das " & vbTab & " bedeuten?"
        
        Call MsgBox("Vorher:" & vbCrLf & TestString)
        TestString = .Replace(TestString, " ($1)")
        Call MsgBox("Nachher:" & vbCrLf & TestString)
    End With
End Sub

Listing 3.2

Dieser Code sucht alle Buchstaben nach einem oder mehr Leerzeichen, Tab oder Enter. Die Leerzeichen werden dann durch ein Einziges ersetzt und der erste Buchstabe des Folgeworts wird in Klammern gesetzt. Mit $1 greifen wir dabei auf den geklammerten Ausdruck im Suchpattern zu. Auf diese Weise lässt sich auf jede Klammer zugreifen: mit einem Dollarzeichen $ gefolgt von der Zahl der Klammer. Achtung: hierbei zählen auch geschachtelte Klammern.

Auf diese Weise erhält man bereits eine gewisse Interaktivität. Noch mehr Kontrolle über die Art der Ersetzung jedoch erhält man mit der MatchCollection:

Private Sub Command3_Click()
    Dim TestString As String
    Dim Matches As MatchCollection
    Dim CurrentMatch As Match
    
    With New RegExp
        .Pattern = "\b([a-z])"
        .Global = True
        
        TestString = "Ich weiß nicht, was soll das bedeuten?"
        
        Call MsgBox("Vorher:" & vbCrLf & TestString)
        
        Set Matches = .Execute(TestString)
        
        For Each CurrentMatch In Matches
            Mid$(TestString, CurrentMatch.FirstIndex + 1) = UCase$(CurrentMatch.Value)
        Next CurrentMatch
        
        Call MsgBox("Nachher:" & vbCrLf & TestString)
    End With
End Sub

Listing 3.3

In diesem Beispiel verwenden wir das Sonderzeichen \b, das für einen Wortanfang oder ein Wortende steht. Das bedeutet, unser Suchausdruck passt auf jeden Buchstaben, der an einem Wortanfang steht.
Nun gehen wir mit Hilfe der MatchCollection die einzelnen Matches durch. Das Ergebnis unserer Mühen: Buchstaben, die am Wortanfang stehen, werden in Großbuchstaben umgewandelt.

3.2 VB.NET

In VB.NET ist die Benutzung nochmal um ein Vielfaches einfacher. Ich habe versucht, die obigen Beispiele so originalgetreu wie möglich zu übertragen, gehe dabei aber auf verschiedene Herangehensweisen von VB.NET ein. Die drei Codebeispiele bieten allerdings nur einen winzigen Einblick in die vielen Möglichkeiten, die regulären Ausdrücke in .NET zu nutzen.

Private Sub Show_IsMatch()
    Dim TestString As String = "http://colinschlueter.de"

    If Regex.IsMatch( _
        TestString, _
        "^http://[a-z]+[-a-z]+(\.[a-z]+)?$", _
        RegexOptions.IgnoreCase Or RegexOptions.Singleline _
    ) Then
        Console.WriteLine(TestString & " ist eine gültige URL")
    Else
        Console.WriteLine(TestString & " ist keine gültige URL")
    End If
End Sub

Listing 3.4

Hier wird die als Shared deklarierte Funktion IsMatch() verwendet, um den Test zu vollziehen. Es gibt auch eine nichtstatische Variante dieser Prozedur.

Private Sub Show_Replace()
    Dim TestString As String = "Ich  weiß   nicht, was  soll das " & vbTab & " bedeuten?"

    Console.WriteLine("Vorher: " & TestString)

    TestString = _
        New Regex( _
            "\s+(\w)", _
            RegexOptions.IgnoreCase Or RegexOptions.Multiline _
        ).Replace(TestString, " ($1)")

    Console.WriteLine("Nachher: " & TestString)
End Sub

Listing 3.5

Dieses Beispiel demonstriert die Verwendung von RegEx.Replace(), um Strings zu ersetzen. Auch hier gibt es sowohl eine statische als auch eine nichtstatische Variante.

Für die Implementierung des dritten Beispiels wird nicht die ebenfalls existierende MatchColleciton verwendet, sondern die sehr mächtige Möglichkeit, Callbackfunktionen zu definieren:

Private Sub Show_Replace_Callback()
    Dim TestString As String = "Ich weiß nicht, was soll das bedeuten?"

    Console.WriteLine("Vorher: " & TestString)

    TestString = _
        New Regex( _
            "\s+(\w)", _
            RegexOptions.IgnoreCase Or RegexOptions.Multiline _
        ).Replace(TestString, New MatchEvaluator(AddressOf ReplaceCallback))

    Console.WriteLine("Nachher: " & TestString)
End Sub

Private Function ReplaceCallback(ByVal Match As Match) As String
    Return Match.Value.ToUpper
End Function

Listing 3.6

4. Ausblick  

4.1 Links

Natürlich waren dies nur kleine Beispiele zur Einführung. Reguläre Ausdrücke bieten in Wahrheit noch einiges mehr an Funktionen. Folgende Links sollten dabei helfen:

4.2 Downloads

Die Codebeispiele gibt es natürlich auch als Download:

Beispiel für VB Classic [1561 Bytes]

Beispiel für VB.NET [1656 Bytes]

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.

Archivierte Nutzerkommentare 

Klicken Sie diesen Text an, wenn Sie die 11 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.

Kommentar von Philipp Stephani am 01.08.2010 um 15:00

@Harold: Fragen zu den Kolumnen bitte in den Foren stellen.

Kommentar von Harold am 27.08.2007 um 19:10

Hallo und danke für die Informationen. Aber wie kann ich mit RegEx(VB.NET) einen Text extrahieren der zwischen zwei Marken liegt?

text text MARKE1 text2 text2 MARKE2 text text text ...

text 2 soll als Eregenis erscheinen.

Kommentar von Bernhard Bloesy am 21.02.2007 um 14:05

Sehr gut gelungen, aber....
iCH bin 58, programmiere nicht (nix gelernt!) und bearbeite Grosstexte = 200 Seiten A4. BEISPIEL: Nun will ich alle Strings loeschen, die nicht aus Grossbuchstaben bestehen. Fazit: Regulaere Ausdruecke nehmen. Sogar WORD kann damit umgehen. Aber solche primitive Arbeitsanleitung wie fuer das BEispiel sucht man lange. Vermutlich werden SIe begreifen koennen, dass IHre Form, etwas zu verbalisieren, den Umgangssprachler bereits "fordert". Oder ich will alle Strings, die aus arabischen Zahlen bestehen, durch ein <CR> ersetzen: => regulaere nehemen, klar.
Fazit: viel mehr einfache BEispiele bitte.
Trotzdem Danke fuer die informative Seite; hilft!
MfG B.Bloesy

Kommentar von Lars Günther am 06.07.2005 um 12:35

Hi,

super Artikel! Hat mir gut und schnell weitergeholfen.
Besten Dank an den Autor!

Lars

Kommentar von Christoph Friedrich am 10.03.2005 um 10:04

Joar
Sehr gut gelungen!!!

Kommentar von Marcus am 14.12.2004 um 10:55

Kann es sein, das als Metazeichen das - (Minuszeichen) fehlt?

Ansonsten ziemlich gut, wobei die Aufteilung mit den Beispielen in der mitte der Beschreibung irritiert!

Gruss und Danke Marcus

Kommentar von greg am 03.12.2004 um 13:05

Das "Beispiel für VB.NET"
funktioniert bei meiner MDE 2002 Version 7.0.9 nicht.
Haben Sie etwas passendes?
Danke!

Kommentar von Ghost_O_Dog am 19.09.2004 um 16:13

Hallo zusammen,

ich bin zwar ein Programmieranfänger, aber was durch die Regular Expressions alles möglich ist, ist schon beeindruckend. Ich benutze ein paar Unix Utilities unter W2K, die eben diese Eigenschaft unterstützen. Nun möchte ich ein Sicherheitstool schreiben, das eben auch diese geniale Erfindung nutzt. Ich möchte mich also in aller Form für das Code Beispiel bedanken und gebe euch auf dem Notensystem eine 1. Weiter so

Ghost_O_Dog

Kommentar von Spatzenkanonier am 04.09.2004 um 22:29

Ohne diese Kolumne wäre ich den regulären Ausdrücken nie auf die Schliche gekommen, und einige meiner Projekte wären nicht möglich gewesen.

Vielen Dank!

Kommentar von Konrad L. M. Rudolph am 23.01.2004 um 09:15

Wer die regulären Ausdrücke unter VB5/6 nutzen möchte, aber davor zurückschreckt, daß man dafür auf die Scripting-Dll zurückgreifen muß und außerdem starke Geschwindigkeitseinbußen in Kauf nehmen muß, dem kann ich übrigens wärmstens empfehlen, sich einmal den Automaten-Generator von vbinside.de anzuschauen.

Die Anwendung erstellt aus einem gegebenen Ausdruck die Übergangstabelle, die in einer Datei (oder als Resource) gespeichert und mit wenigen Codezeilen in ein Programm eingebaut werden kann (in Quellcode des Programms wird gezeigt, wie).

Kommentar von Der Hans am 17.01.2004 um 19:16

Die Mächtigkeit dieser Kolumne steht außer Frage! :D

Ich finde diese Kolumne ist sehr gelungen! Danke an den Autor!