Für das Suchen und Ersetzen von Zeichenketten in einem vorgegebenen Text wurden in einem Projekt einerseits reguläre Ausdrücke und andererseits Methoden zur Manipulation von Zeichenketten kombiniert eingesetzt. Sie können im Text nach unterschiedlichen – fest vorgegebenen – Zeichenketten suchen, die eine spezielle Bedeutung haben oder Ihre Muster selbst eintragen:
Abbildung 19.6.6.1: Suchen und Ersetzen von Zeichenketten in einem Text
Es hat sich herausgestellt, das für komplexe Texte für jede Klasse von Zeichenketten ein Muster so konstruiert werden muss, das es mindestens ein Alleinstellungsmerkmal hat, das es von anderen Klassen unterscheidet. Sonst könnten Sie zum Beispiel den Geldwert 12,44 € nicht von 12,44 als normaler Dezimalzahl unterscheiden. Gegenwärtig können Sie nur nach ISBN (10) suchen, die nach ISO 2108 mit Trennstrichen formatiert sind.
Der Quelltext wird fast vollständig angegeben, wobei Ihnen vor allem das Zusammenspiel von regulären Ausdrücken und Methoden zur Manipulation von Zeichenketten gezeigt werden soll:
' Gambas class file Private $rExpression As Regexp Private $sPattern As String Public Sub Form_Open() $rExpression = New Regexp ... End ' Form_Open() Public Sub btnSearch_Click() If Not cbxRegexpression.Text Then Message.Error("Es ist KEIN Suchtext vorhanden!") cbxRegexpression.SetFocus Return Endif ' Not cbxRegexpression.Text ? Try $rExpression.Compile(SetPattern(cbxRegexpression.Text)) ' Fehler im Muster abfangen! If Error Then Message.Error("FEHLER IM REGULÄREN AUSDRUCK!") Return Endif ' Error ? lbxSearch.List = Search(txaText.Text) End ' btnSearch_Click() Public Sub btnReplace_Click() If Not cbxRegexpression.Text Then Message.Error("Es ist KEIN Suchtext vorhanden!") Return cbxRegexpression.SetFocus Endif ' Not cbxRegexpression.Text ? If Not txtReplace.Text Then If Message.Error("KEIN Text vorhanden!", "Mit NICHTS ersetzen!", "Abbrechen!") = 1 Then Try $rExpression.Compile(SetPattern(cbxRegexpression.Text)) If Error Then Message.Error("FEHLER IM REGULÄREN AUSDRUCK!") Return Endif ' Error ? txaText.Text = TextReplace(txaText.Text, txtReplace.Text) Else Return cbxRegexpression.SetFocus Endif Endif ' Not cbxRegexpression.Text ? End ' btnReplace_Click() Private Function Search(sText As String) As String[] Dim aSearchList As New String[] Dim iStart As Integer = 1 Try $rExpression.Exec(sText) ' ---> Fehler abfangen! If Error Then Message.Error("Es trat ein Fehler auf ...!") Return Endif ' Error ? While $rExpression.Offset <> -1 aSearchList.Add($rExpression.Text) iStart += $rExpression.Offset + Len($rExpression.Text) If iStart > Len(sText) Then Break $rExpression.Exec(Mid$(sText, iStart)) Wend Return aSearchList End ' Function Search(..) Private Function TextReplace(sText As String, sReplace As String) As String Dim iStart As Integer = 1 Try $rExpression.Exec(sText) ' ---> Fehler abfangen! If Error Then Message.Error("Es trat ein Fehler auf ...!") Return Endif ' Error ? While $rExpression.Offset <> -1 iStart += $rExpression.Offset sText = Mid$(sText,1,iStart - 1) & sReplace & Mid$(sText, iStart + Len($rExpression.Text)) iStart += Len(sReplace) If iStart > Len(sText) Then Break $rExpression.Exec(Mid$(sText, iStart)) Wend Return sText End ' Function TextReplace(..) 'Die Funktion SetPattern() ist nur notwendig, um den Mustern einen Hinweistext voranzustellen. Private Function SetPattern(sInput As String) As String Dim iPosition As Integer iPosition = InStr(sInput, "--->") If iPosition = 0 Then $sPattern = sInput Else $sPattern = Replace(sInput, Left(sInput, iPosition + 3), "") $sPattern = Trim($sPattern) Endif ' iPosition = 0 ? Return $sPattern End ' Function SetPattern(..)
Als Besonderheit werden im Projekt die beiden Methoden Regexp.Compile() und Regexp.Exec() eingesetzt.
Syntax: Sub Compile ( Pattern As String [ , CompileOptions As Integer ] )
Mit der Methode Compile() können Sie einen regulären Ausdruck (Pattern) für die spätere Ausführung durch die Exec-Methode vor-kompilieren. Dies ist nützlich, wenn Sie ein Muster oft für sehr viel Text einsetzen wollen.
Syntax: Sub Exec ( Subject As String [ , ExecOptions As Integer ] )
Die Methode Exec() ermöglicht Ihnen den Einsatz eines zuvor kompilierten regulären Ausdruck Dies ist vor allem nützlich, wenn Sie viele verschiedene Texte prüfen wollen. Sie müssen einen regulären Ausdruck nur einmal kompilieren und können dann Exec(..) wiederholt für verwenden, was eine höhere Geschwindigkeit erwarten lässt.
Die Methoden Compile(..) und Exec(..) werden automatisch ausgeführt, wenn Sie ein Muster (Pattern) und einen Text (Subjekt) angeben und ein (neues) Regexp-Objekt aufrufen.
Eine Auswahl der folgenden Konstanten können Sie als Option in den beiden Methoden einsetzen:
Anchored BadMagic BadOption BadUTF8 BadUTF8Offset Callout Caseless DollarEndOnly DotAll Extended Extra MatchLimit MultiLine NoAutoCapture NoMatch NoMemory NoSubstring NoUTF8Check NotBOL NotEOL NotEmpty Null UTF8 Ungreedy UnknownNode
Beispiel: Regexp.Anchored – Konstante Anchored As Integer = 16
Wenn diese Konstante als Option angegeben ist, wird das Muster auf die erste passende Stelle im Subjekt „verankert“. Dieser Effekt kann auch durch geeignete Konstrukte im Muster selbst erreicht werden.
Im nächsten Quelltext-Ausschnitt aus einem Projekt zur Konvertierung von Gambas-Quelltext in HTML-Quelltext wird u.a. im Gambas-Quelltext nach einer URL gesucht und bei positivem Ergebnis durch einen passenden Hyperlink ersetzt:
Private Sub parseLinks(sURL As String) As String Dim sRegex As Regexp Dim sPattern, sReplace As String sPattern = "(https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.-]*(\\?\\S+)?)?)?)|(@[\\w]*|#[\\w]*)" sRegex = New Regexp(sURL, sPattern) sReplace = "<a href=\"" & sRegex.Text & "\">" & sRegex.Text & "</a>" Return Replace(sURL, sRegex.Text, sReplace) End ' parseLinks(..) Public Sub Test_Click() Print parseLinks("http://www.gambas-buch.de") End
Das Ergebnis kann sich sehen lassen:
<a href="http://www.gambas-buch.de">http://www.gambas-buch.de</a>