niedziela, 18 października 2009

RegExp - jak to wykorzystać

Wstęp
W dzisiejszej odsłonie pokażę przykładowe wykorzystanie wyrażeń regularnych popularnie nazywanych Reular Expresion lub RegExp. Jest to potężne narzędzie służące do testowania, wyszukiwania lub podmiany tekstu na podstawie specyficznego wzorca - Patternu.
Wzorzec ten na pierwszy rzut oka przypomina spagetti - jakiś dziwny ciąg znaków bez ładu i składu. Nic bardziej mylnego. Ciąg ten jest aż do bólu logiczny, a każdy znaczek w nim coś oznacza.

Podstawy
Pierwszym krokiem do rozpoczęcia pracy z RegExp-ami jest zrozumienie zasady działania tego machizmu. najogólniej można go opisać jako "dopasowanie do wzorca". Wzorzec ten ma w sobie zakodowane informacje umożliwiające porównanie fragmentu tekstu i wyłowienie go w przypadku gdy tekst porównywany zgodzi się z wzorcem. niekoniecznie dosłownie, przeważnie logicznie.
Prostym przykładem obrazującym mechanizm wzorca jest dobrze wszyskim znany znak * występujący przy filtrowaniu w Excelu lub Accessie. Znak ten zastępuje dowolne inne znaki w dowolnej ilości. Czyli jak nasz wzorzec wyglądał by w następujący sposób: LUB* to wyłapał by wszystkie możliwe zdania rozpoczynające się od LUB np. Lublin, Lublinianka, Lublinianin, Lubczyk itp. Innym sposobem wykorzystania gwiazdki jest umieszczenie znaku * na początku frazy np. *AWA. Wzorzec taki pasował by do każdego zdania lub słowa kończącego się w określony sposób. Pasowało by tu np. Warszawa, kawa i wiele innych słów. Ostatnim sposobem wykorzystania gwiazdki jest forma zwierająca znak * na końcu jak i na początku np. *kli*. do takiego wzorca pasuje każde słowo posiadające wymienioną frazę np. wyklinać.

Kolejnym krokiem w użytkowaniu filtrów jest dodanie znaku zastępującego pojedyncza literę. W przypadku Excela i Access jest to znak '?'. Można go stosować samodzielnie jak i w kombinacji z poprzednio omawianym znakiem '*', dzięki czemu możemy zawężać filtrowane dane do interesującego nasz zakresu. Przykładem filtra mogło by być: dw?j* . Wzorzec takie pasował by do słów dwójka, dwoje, dwójkowy itp.

W przypadku Access-a oraz instrukcji Like która umożliwia filtrowanie danych na podstawie wzorca dochodzi nam kilka opcji standardowo niedostępnych w Excelu. jest to znak zastępujący dowolną cyfrę - # np. wzorzec LU# * odnajdzie nam wszystkie ciągi znaków rozpoczynające się od LU, posiadające następnie dowolną cyfrę, następnie znajduje się spacja i dowolne znaki.

Kolejnym elementem obecnym w Accessie a nie obecnym w standardowym filtrowaniu Excel-a to zakresy oznaczane za pomocą nawiasów kwadratowych [] np. [1-9] oznacza cyfry od 1 do 9 z pominięciem 0 gdyż nie znajduje się ono miedzy wymienionymi znakami. Znak minusa oznacza że mówimy o przedziale znaków od pierwszego do ostatniego zgodnie z umiejscowieniem w standardzie ASCII. Ponadto konstrukcja taka zastępuje pojedynczy znak i może być dowolnie łączona z wcześniej wymienionymi znakmi.
Ostatnią opcją dostępną w Accessie jest wyłączenie zbioru znaków realizowane z pomocą konstrukcji z nawiasów klamrowych wraz z wykrzyknikiem [!] - przykładem może być: [!a-c]* . Konstrukcja taka sprawi że z wyników filtrowania zostaną wyłączone wszystkie zdania rozpoczynające się na litery a,b i c.

Osobną kwestią jest operator Like z VBA. Umożliwia on sprawdzenie w kodzie czy string tekstowy pasuje do porównywanego wzorca. Odpowiedzią jest wartość logiczna prawda lub fałsz.
przykładem zastosowania może być warunek w instrukcji IF lub ELSEIF.

Sub test()
    Dim t As String
    t = "test"

    If t Like "te??" Then
        Debug.Print "pasuje"
    Else
        Debug.Print "nie pasuje"
    End If
End Sub

Dodatkowo należy wspomnieć że klauzula Like przyjmuje jako wzorce wszystkie wspomniane parametry czyli *, ?, #, [] oraz [!].

Techniki bardziej zaawansowane

W momencie gdy wymienione techniki nie zdają egzaminu lub też gdy potrzebujemy czegoś nie osiągalnego w opisywany sposób sięgamy po narzędzia bardziej wysublimowane, lecz trudniejsze w wykorzystaniu. mam na myśli wcześniej wspomniane Regular Expression - czyli RegExp-y.
Narzędzie to nie jest standardowo dostępne w VBA, więc aby go wykorzystać należy albo dodać referencję do projektu biblioteki Microsoft VBScript Regular Expressions 5.5.

Dostarcza ona metod, właściwości i kolekcji używanych w wyszukiwaniu, testowaniu i zastępowaniu z wykorzystaniem wzorców. Obiekt Ten ma następujące właściwości:
Pattern - tu wpisujemy wzorzec
IgnoreCase - tu możemy ustawić czy uwzględniamy wielkość liter podczas operacji
Global - Możemy wymusić przeszukiwanie całego tekstu lub też zakończyć operację po pierwszym udanym dopasowaniu
MultiLine - Ta opcja sprawia że tekst zawierający znak końca linii jest dzielony na wirtualne mniejsze teksty które są sprawdzane każde oddzielnie, zaś znak końca linii jest pomijany podczas sprawdzania. Opcja ta daje pożądane rezultaty wraz z opcją Global

Ponadto występują następujące metody:
Test - umożliwia sprawdzenie czy dany wzorzec pasuje do badanego ciągu tekstowego
Execute - zwraca kolekcję MatchCollection zawierającą wszystkie dopasowania zgodnie z wzorcem
Replace - umożliwia zamianę tekstu pasującego do wzorca na inny podany w parametrze

Przykładowe wykorzystanie poszczególnych metod.

Test
Sub reg_test()

Dim r As New RegExp
Dim sIn As String
Dim bOut As Boolean

sIn = "to jest test " & VBA.vbCrLf & " to jest kolejny test"

With r
.Pattern = "test"
.IgnoreCase = True
.Global = False
.MultiLine = False
bOut = .Test(sIn)
End With

If bOut Then
Debug.Print "wzorzec odnaleziony w przeszukiwanym stringu"
Else
Debug.Print "brak przypisania"
End If

End Sub
Replace
Sub reg_replace()

Dim r As New RegExp
Dim sIn As String
Dim sOut As String
Dim sReplace As String

sIn = "to jest test " & VBA.vbCrLf & " to jest kolejny test"
sReplace = "ble"

With r
.Pattern = "test"
.IgnoreCase = True
.Global = True
.MultiLine = False
sOut = .Replace(sIn, sReplace)
End With

Debug.Print sOut

End Sub
Execute

Sub reg_execute()

Dim r As New RegExp
Dim colMatches As MatchCollection
Dim objMatch As Match

Dim sIn As String

sIn = "to jest test " & VBA.vbCrLf & " to jest kolejny test"

With r
.Pattern = "test"
.IgnoreCase = True
.Global = True
.MultiLine = False
Set colMatches = .Execute(sIn)
End With

For Each objMatch In colMatches
Debug.Print objMatch.Value, objMatch.FirstIndex
Next

End Sub
Zakończenie
Opisane metody są w zasadzie wprowadzeniem do rozległego tematu jakim est wyłuskiwanie informacji z tekstu na podstawie wzorów. W kolejnej części naświetlę szczegóły związane z budowaniem wzorców (Pattern) wykorzystywanych w życiu codziennym

Brak komentarzy:

Prześlij komentarz