Die Community zu .NET und Classic VB.
Menü

VB 5/6-Tipp 0572: Reguläre Ausdrücke in VB benutzen

 von 

Beschreibung 

Dieser Tipp enthält zwei rle-algorithmen (komprimierung), einmal mit VB-Schleifen umgesetzt und einmal mit dem RegEx-Objekt in VB. Beide Verfahren werden per API genau abgestoppt um zu demonstrieren, das das RegEx-Objekt schneller ist. Zudem wird erklärt wie man überhaupt RegExes in VB einsetzt.

Schwierigkeitsgrad:

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

GetTickCount, QueryPerformanceCounter, QueryPerformanceFrequency

Download:

Download des Beispielprojektes [3,08 KB]

'Dieser Quellcode stammt von http://www.activevb.de
'und kann frei verwendet werden. Für eventuelle Schäden
'wird nicht gehaftet.

'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
'Ansonsten viel Spaß und Erfolg mit diesem Source!

'------- Anfang Projektdatei Regulaere Ausdruecke.vbp -------
' Es muss ein Verweis auf 'Microsoft VBScript Regular Expressions 5.5' gesetzt werden.

'--- Anfang Formular "Form1" alias Regulaere Ausdruecke.frm ---
' Steuerelement: Textfeld "Text1"
' Steuerelement: Schaltfläche "Command1"
' Steuerelement: Beschriftungsfeld "Label1"

'
'Autor: Dominik Auras - neo@tipsntricks.de
'       http://www.vbinside.de

Option Explicit

Private Declare Function GetTickCount Lib "kernel32" () As Long

Private Declare Function QueryPerformanceCounter Lib "kernel32" ( _
   lpPerformanceCount As LARGE_INTEGER) As Long
   
Private Declare Function QueryPerformanceFrequency Lib "kernel32" ( _
   lpFrequency As LARGE_INTEGER) As Long

Private Type LARGE_INTEGER
  lowpart As Long
  highpart As Long
End Type

Dim freq As LARGE_INTEGER, calibration As Double

Private Sub Command1_Click()
  Dim Content As String, i As Long, c As Long, e As Long
  Dim a As String, b As String, reRLE As New RegExp
  Dim colMatches As MatchCollection, reMatch As Match
  Dim Ret As String, OldC As String, OldRet As String
  Dim Start As LARGE_INTEGER, Ende As LARGE_INTEGER
  
    e = 100& * 1024&
  
    'Zufälligen Text erzeugen, der nachher komprimiert werden soll
    Randomize Timer
    Do While Len(Content) < e
      i = Rnd * 254 + 1
      If i > e - Len(Content) Then i = e - Len(Content)
      OldC = c
      Do
        c = Rnd * 255
      Loop Until OldC <> c
      
      Content = Content & String(i, c)
    Loop
    
    Debug.Print "Stringgröße: " & Len(Content)
    Text1.Text = Text1.Text & "Stringgröße: " & Len(Content) & vbCrLf
    
    QueryPerformanceCounter Start
    
    '#############
    'Komprimierung mit VB-Schleife (RLE-Algo)
    'API-Zeitmessung
    
    a = ""
    b = ""
    c = 0
    b = Mid$(Content, 1, 1)
    
    For i = 1 To Len(Content)
      a = Mid$(Content, i, 1)
      
      If b = a Then
        c = c + 1
      Else
        Ret = Ret & Chr$(c) & b
        b = a
        c = 1
      End If
    Next i
    Ret = Ret & Chr$(c) & b
    '#############
    QueryPerformanceCounter Ende
    
    Debug.Print "VB komprimiert " & Len(Ret) & ": ";
    Debug.Print Int(((CDouble(Ende) - CDouble(Start)) / _
                    CDouble(freq) * 1000 - calibration) * _
                    100000000000#) / 100000000000# & " ms"
                    
    Text1.Text = Text1.Text & "VB komprimiert " & Len(Ret) & ": " & _
                 Int(((CDouble(Ende) - CDouble(Start)) / _
                    CDouble(freq) * 1000 - calibration) * _
                    100000000000#) / 100000000000# & " ms" & vbCrLf
    
    OldRet = Ret
    Ret = ""
    
    QueryPerformanceCounter Start
    
    '#############
    'Derselbe Algorithmus zur Komprimierung nun mit einem
    'regulären Ausdruck
    '+ API-Zeitmessung
    
    reRLE.Pattern = "(.|\n|\r)\1*"
    reRLE.Global = True
    'das allseits bekannte /../g in Perl etc.
    
    Set colMatches = reRLE.Execute(Content)
    'RegEx anwenden und _alle_ Fundstellen speichern
    
    'Fundstelle durchgehen
    For i = 0 To colMatches.Count - 1
      Set reMatch = colMatches(i)
      Ret = Ret & Chr$(reMatch.Length) & reMatch.SubMatches(0)
    Next i
    '#############
    
    QueryPerformanceCounter Ende
    
    Debug.Print "RegEx komprimiert " & Len(Ret) & ": ";
    Debug.Print Int(((CDouble(Ende) - CDouble(Start)) / _
                    CDouble(freq) * 1000 - calibration) * _
                    100000000000#) / 100000000000# & " ms"
                    
    Text1.Text = Text1.Text & "RegEx komprimiert " & Len(Ret) & ": " & _
                 Int(((CDouble(Ende) - CDouble(Start)) / _
                    CDouble(freq) * 1000 - calibration) * _
                    100000000000#) / 100000000000# & " ms" & vbCrLf
                    
    'Kontrolle des RLE-Algortihmus
    If OldRet = Ret Then
      Debug.Print "Daten stimmen überein"
      Text1.Text = Text1.Text & "Daten stimmen überein" & vbCrLf
    End If
    
    For i = 1 To Len(Ret)
      If i > Len(OldRet) Then
        Debug.Print "pos", i, "char", Mid$(Ret, i, 1)
      Else
        If Mid$(Ret, i, 1) <> Mid$(OldRet, i, 1) Then
          Debug.Print "pos", i, "char", Mid$(Ret, i, 1)
        End If
      End If
    Next i
    
    Text1.Text = Text1.Text & "http://www.vbinside.de" & vbCrLf
End Sub

Private Function CDouble(Num As LARGE_INTEGER) As Double
  Dim Low As Double, High As Double
  
    Low = Num.lowpart
    High = Num.highpart
    
    If Low < 0 Then Low = 4294967296# + Low + 1
    If High < 0 Then High = 4294967296# + High + 1
    
    CDouble = Low + High * 4294967296#
End Function

Private Sub Form_Load()
  Dim Start As LARGE_INTEGER, Ende As LARGE_INTEGER
  
    QueryPerformanceFrequency freq
  
    QueryPerformanceCounter Start
    QueryPerformanceCounter Ende
    
    calibration = (CDouble(Ende) - CDouble(Start)) / _
                  CDouble(freq) * 1000
End Sub
'--- Ende Formular "Form1" alias Regulaere Ausdruecke.frm ---
'-------- Ende Projektdatei Regulaere Ausdruecke.vbp --------

Tipp-Kompatibilität:

Windows/VB-VersionWin32sWin95Win98WinMEWinNT4Win2000WinXP
VB4
VB5
VB6

Hat dieser Tipp auf Ihrem Betriebsystem und mit Ihrer VB-Version funktioniert?

Ja, funktioniert!

Nein, funktioniert nicht bei mir!

VB-Version:

Windows-Version:

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 10 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 Klaus Schweitzer am 10.02.2009 um 10:47

If Low < 0 Then Low = 4294967296# + Low + 1
If High < 0 Then High = 4294967296# + High + 1
Ist diese Berechnung von einer signed zu einer unsigned
Variablen richtig ?? Beispiel: 1 Byte: 1111 1111 = 255
ohne Vorzeichen, -1 mit Vorzeichen 2^8 = 256 + (-1) = 255
also müsste die Berechnung für eine Long-Variable doch lauten 2^32 = 4294967296 + Low (ohne "+1")

Kommentar von am 19.08.2005 um 17:32

RegExp sind Teil des VBScript-Paketes vom M$; dieses muß man extra herunterladen und installieren !

Kommentar von Kai Schmalstieg am 16.03.2005 um 09:34

Hallo, ich möchte diesen Tipp testen, kann aber keinen Verweis auf 'Microsoft VBScript Regular Expressions
' 5.5' setzen. Icjh klicke es zwar an und bestätige es, es wird aber irgendwie ignoriert. Was kann ich tun?

Kommentar von Johannes Roth am 06.01.2005 um 20:59

Darum gehts doch gar nicht!!! Es geht hier nicht darum, zu zeigen dass der eine schneller als der andere ist - RegExps werden wie da auch steht schneller - sondern allgemein um Regular Expressions zu zeigen!

Kommentar von Jochen Müller am 18.03.2004 um 09:03

und was bringt das - effektiv fast nichts?!?!? :-)
Rechner (P4 mit HT 3000 MHz). Aber den VB Code könnte man noch optimieren :-)

--
Stringgröße: 102400
VB komprimiert 1590: 35,40227709239 ms
RegEx komprimiert 1590: 35,39276423572 ms
Daten stimmen überein

Kommentar von Oliver Schütze am 07.08.2003 um 16:38

Thomas Fuessl hat zu diesem Thema eine gute DLL geschrieben:
http://www.cae-software.com/freeware/regexp.dll/
Diese DLL hat den Vorteil, dass man nicht das ganze VBS zu installieren braucht.

Gruß,
O. Schütze

Kommentar von Jan-Christian Krause am 25.07.2003 um 12:58

Hallo Leute,

hier noch ein kleiner Hinweis: Wenn Ihr einen Verweis auf die Bibliothek "Microsoft VBScript Regular Expressions 5.5" in Eurem VBA-Projekt erstellt, dann könnt Ihr auch dort reguläre Ausdrücke verwenden ;-).

Ich habe das mit Access 2000 getestet.

Mit freundlichem Gruss
Jan-Christian Krause

Kommentar von Konrad Rudolph am 13.06.2003 um 14:50

Ladet euch doch mal die Beispieldatei runter und schaut euch die Verweise an!

Die RegExp-Klasse ist in der VBS-Dll!

Kommentar von elite01 am 20.05.2003 um 18:05

Bei mir das gleiche es scheint garkein RegExp zu geben hab mich gleich etwas gewundert

Kommentar von Paul am 02.05.2003 um 19:13

Bei mir (VB 6) wird folgende die Fehlermeldung angezeigt:
"User-defined type not defined".
Anschließend wird ", reRLE As New RegExp" markiert.
Was soll ich tun?