środa, 31 lipca 2013

Testowanie zgodności ciągów tekstowych- wyrażenia regularne RegExp- 3/4

Zanim uruchomimy pierwszą pełną procedurę z wykorzystaniem techniki wyrażeń regularnych (RegExp) przyjrzyjmy się dodatkowo właściwościom obiektu RegExp

.Pattern       pozwoli nam zdefiniować wzorzec porównawczy,
.Global        określa, czy wzorzec dotyczy pierwszego (= False), 
               czy wszystkich wystąpień w tekście (= True),
.IgnoreCase    określa sposób testowania wyrażenia ze względu na wielkość liter (domyślnie =False,
               wyszukiwanie binarne uwzględniające wielkość liter),

oraz metodom obiektu Regexp:
.Test       zwraca informację czy można dopasować wyrażenie do ciągu tekstowego,
.Replace    dokonuje zamiany fragmentu wzorcowego na nowy wskazany ,
.Execute    wykonuje operację zwracając obiekt Match z kolekcji MatchCollection.

W dużym skrócie podsumowując powyższe elementy obiektu  RegExp określę to w sposób następujący- pozwalają one na wskazanie wzorca a następnie dokonanie zamiany fragmentu tekstu na inny lub pobranie poszczególnych elementów w całości lub dla pierwszego wystąpienia.

Czas na zebranie całości zagadnienia w konkretne rozwiązania i prezentację przykładowych pełnych konstrukcji kodu VBA. Wykonując poniższe operacje w środowisku VBA proszę nie zapomnieć o Kroku 1, a więc ustanowieniu referencji do biblioteki RegExp.

Przykład 1. zamiana wyrazów w ciągu tekstowy, wyraz 'jest' na 'był'


Przykład 2. z podanego ciągu tekstowego pozostawić tylko cyfry
 

Przykład 3. z podanego ciągu tekstowego usunąć wszystkie liczby


Przykład 4. W przykładzie nr 2 dodatkowo pozostały podwójne spacje oraz zbędna spacja przed kropką i wykrzyknikiem. To wszystko także chcemy usunąć i wyprostować. W tej sytuacji utworzymy kaskadowy mechanizm RegExp:

Przykład 5. W powyższym przykładzie zastosowana została technika zamiany kolejności wyrazów. Jest to jedna z wielu dodatkowych korzyści pracy z RegExp. Poniżej prosty przykład, który zamienia kolejność 3 pierwszych wyrazów podanego tekstu:

Przykład 6. Z podanego tekstu chcemy pobrać tylko adres e-mai. W tym celu wykorzystamy jeden z wielu możliwych wzorców odpowiadających adresowi e-mail i stworzymy następujący kod:

Powyższy przykład zamiast metody .Replace wykorzystuje metodę .Execute. Ale o tym napiszę już w kolejnym wpisie za kilka dni...


Osobom, które są zainteresowane wyrażeniami regularnymi polecam poniższe linki, które pozwolą na poszerzenie i ugruntowanie informacji przedstawionych w ostatnich postach. Linki te poświęcone są ogólni RegExp i niekoniecznie wskazują na bezpośrednie wykorzystanie tej techniki w VBA.

Korzystanie z wyrażeń regularnych w programie Microsoft Visual Basic 6.0Regular-Expressions.Info
.NET Framework Regular Expressions
RegExp Help
Regular-Expressions.info
Introduction to Regular Expressions

poniedziałek, 22 lipca 2013

Testowanie zgodności ciągów tekstowych- wyrażenia regularne RegExp- 2/4

Kontynuując temat tworzenia wyrażeń regularnych RegExp omówię najważniejszą umiejętność związaną z tą techniką, a więc budowanie wzorców porównawczych.
 

Krok 2.
To najtrudniejsza część pracy z RegExp- budowa składni tworzącej kryteria. Spojrzymy na to zadanie najpierw przez pryzmat wybranych znaków (kodów) specjalnych, następnie przedstawię proste przykłady, a na koniec zaprezentuję kilka złożonych wzorców.

A) Znaki i symbole specjalne
\d    cyfra
\D    nie cyfra
\s    spacja
\S    nie spacja
\w    znak alfanumeryczny, litera
\W    nie znak alfanumeryczny
\b    granica słowa, pozycja między słowem a spacją
\n    znak nowej linii (vbCrLf, Chr(10), Chr(13), vbNewLine)
\r    znak nowej linii (Chr(13))
\t    znak tabulacji (vbTab)
.     (kropka) dowolny znak z wyjątkiem znaku nowej linii
*     powtórzenie symbolu dowolną ilość lub zero razy
?     powtórzenie symbolu zero lub jeden raz
+     powtórzenie poprzedniego wyrażenia co najmniej raz
\     używany jako znak wyjścia dla znaków specjalnych
^     na początku tekstu
      także symbol zaprzeczenia(patrz poniżej)
$     na końcu tekstu
[]    przedział znaków
      [A-Z]  dowolna wielka litera
      [a-z]  dowolna mała litera
      [0-9]  dowolna cyfra
      [^0-9] nie zawiera cyfry
{}    wskazuje ilość dopuszczalnych powtórzeń: 
      a{1}   jednokrotne powtórzenie litery a
      a{0,2} zero do dwóch powtórzeń litery a
()    grupowanie
|     alternatywa dla grupowania

Proszę jednocześnie pamiętać, że dla prostych wyrażeń bez udziału powtórzeń i znaków specjalnych zastosujemy technikę podobną do tej opisanej przy pracy z operatorem Like w jednym z wcześniejszych postów. RegExp jest także, co do zasady, wrażliwy na wielkość liter

Spójrzmy na przykłady:
RegExp Pattern   Dopasowanie    Wyjaśnienie (opcjonalne)
           (czerwonym-dopasowanie)
abc              abcabcabc
234              1234567
Jan              Jan
                 Janek
                 janek          wielkość liter ma znaczenie
ab*c             acde
                 abcde
                 abbbbcde
ab?c             acde
                 abcde
                 abbbcde        brak dopasowania
ab+c             acde           brak dopasowania
                 abcde
                 abbbcde
ab.d             abcd
                 ab1d
                 abc1d          brak dopasowania 
a.*d             ad
                 abcd
                 asfas13wbd
\d\d             10
                 99
                 100
                 9999           dwa podwójne układy cyfr
\w+              alfa           dowolny, każdy wyraz
                 Witaj Jan! 
\w+@\w+          a@a            uproszczony schemat dla e-maila
                 email@domena.pl
\w+@\w+.\w+      email@domena.pl
                 jan.kowalski@domena.pl
^ab.*c           abc
                 ab123fdcdef
                 babc           tekst nie zaczyna się od a
^ab.*c$          abc
                 ab123c
                 ab123cd        nie kończy się na c
                 ab123cdc       powtórzenie c nie ma znaczenia
                 bacdc          nie zaczyna się od a
^\d              1abc           zaczyna się od cyfry
\d$              abc1           kończy się cyfrą
[abc]            abc            znaki wskazane w nawiasie
                 abcdef
                 abcdefabc   
[^abc]           abcdefabc      nie a, nie b, nie c     

[A-Z]            abcDEF         wielkie litery
                 ABCDEF
                 abcdef
^[A-Z].+         Abc123d        zaczyna się od wielkiej litery
                 abc123d
[+*?.]           ..??**++       nawiasy likwidują znaczenie znaków specjalnych
^[1-9][0-9]*$    1              liczba całkowita większa od zera
                 1000
                 -1000
                 123.45         tylko liczba całkowita
(ab)+            ab
                 ababab
                 bababa
(ab|ba)+         ab
                 ba
                 ababab         rozpozna jako jeden ciąg
                 bacbacab       rozpozna trzy ciągi
                 abcdef
(abc)?           abc            ale także dla pustego ciągu
a(\d+)c          a123c          zawiera cyfry pomiędzy a i c
                 a1c
                 ac
                 abc  
a{2}             alfaabeta
a{1,2}           alfaabeta

Inne gotowe przykłady z tego źródła:
A) weryfikacja, czy podano prawidłowy e-mail:
^[A-Za-z0-9_\.-]+@[A-Za-z0-9_\.-]+[A-Za-z0-9_][A-Za-z0-9_]$

Wskazówka! w sieci znaleźć można wiele przykładów weryfikacji adresów e-mail, kolejny z nich podam w trzeciej lekcji poświęconej RegExp. Zainteresowanych tym zagadnieniem odsyłam do tej dyskusji.

B) weryfikacja zapisu daty w układzie: yyyy-MMM -dd, gdzie MMM to trzyliterowy skrót zapisany z wielkiej litery:
^\d\d\d\d-[A-Z][a-z][a-z]-\d\d$

C)  weryfikacja daty jak powyżej rozszerzona, sprawdzamy, czy miesiąc podany w języku polskim lub angielskim:
^20\d\d-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(0[1-9]|[1-2][0-9]|3[01])$ 

^20\d\d-(Sty|Lut|Mar|Kwi|Maj|Cze|Lip|Sie|Wrz|Paź|Lis|Gru)-(0[1-9]|[1-2][0-9]|3[01])$