AutoIt/Wyrażenia regularne

Co to są wyrażenia regularne

edytuj

Wyrażenia regularne to wzorce utworzone ze znaków i metaznaków, które w wyrażeniu pełnią ściśle określone funkcje. Łańcuchy znakowe można porównywać z tymi wzorcami w poszukiwaniu dopasowań, lub przekształcać zgodnie z regułami w nich zapisanymi. Opanowanie zasad tworzenia wyrażeń regularnych może być dość czasochłonne, ale udostępniają one programiście bardzo wydajne narzędzie testowania i przetwarzania tekstów.


Składniki wyrażenia regularnego

edytuj

Wyrażenia regularne składają się z następujących elementów:

Zwykłe znaki

edytuj

Zwykłe znaki we wzorcu reprezentują same siebie np. wzorzec "Ala ma kota" pasuje do części tekstu identycznej z tym wzorcem.

Zwykłymi znakami są wszystkie znaki z wyjątkiem metaznaków, które nie oznaczają tego samego, co ich zapis, lecz są interpretowane w pewien specjalny sposób.


Metaznaki

edytuj

Metaznaki rozpoznawane poza nawiasami kwadratowymi:

\  - ogólny znak zmiany znaczenia, różnie wykorzystywany
.  - dowolny znak oprócz znaku nowego wiersza
[  - oznaczenie początku definicji klasy znaków
|  - początek alternatywnej gałęzi, odpowiednik logicznego OR
(  - początek podwyrażenia
)  - koniec podwyrażenia
?  - rozszerzenie znaczenia
*  - kwantyfikator "zero lub więcej"
+  - kwantyfikator "jeden lub więcej"
{  - początek kwantyfikatora "min/max"
^  - początek tekstu
$  - koniec tekstu

Część wzorca ujęta w nawiasy kwadratowe jest zwana "klasą znaków". Wewnątrz klasy znaków rozróżniane są jedynie następujące metaznaki:

\  - ogólny znak zmiany znaczenia
^  - zaprzeczenie logiczne klasy, ale tylko gdy występuje na pierwszej pozycji, w innym miejscu jest traktowany jako zwykły znak
-  - wskazuje zakres znaków
]  - oznaczenie końca definicji klasy znaków

Aby we wzorcu uzyskać znak będący metaznakiem, ale w znaczeniu odpowiadającym jego zapisowi, należy go poprzedzić ukośnikiem np.:

\. oznacz kropkę

\\ oznacza ukośnik itp.


Znaki specjalne

edytuj

Oprócz zwykłych znaków we wzorcach można używać znaków specjalnych. Rozpoczynają się one od ukośnika:

\a - sygnał dźwiękowy BEL, jak chr(7)
\c - klawisz ctrl, np. \cM oznacza ctrl-M
\d - dowolna cyfra
\D - dowolny znak nie będący cyfrą
\e - escape, jak chr(27)
\E - koniec modyfikacji
\f - znak wysuwu strony, jak chr(12)
\h - znak tabulatora chr(9) lub nowego wiersza chr(10)
\H - znak nie będący tabulatorem i znakiem chr(10)
\n - znak nowego wiersza, jak @LF, chr(10)
\N - nowy wiersz (patrz: Inne nowości w wersji 3.3.10.2 AutoIt'a)
\Q - wyłączenie interpretacji metaznaków we wzorcu, aż do napotkania \E
\r - znak powrotu kursora, jak @CR, chr(13)
\R - nowy wiersz (patrz: Nowości w wersji 3.3.10.2 AutoIt'a)
\s - dowolny biały znak (znaki od chr(9) do chr(13))
\S - dowolny czarny znak
\t - tabulatora poziomy, jak chr(9)
\v - tabulator pionowy, jak chr(10), chr(11), chr(12) lub chr(13)
\V - znak nie będący tabulatorem pionowym
\w - znak słowa, znaki alfanumeryczne a-z, A-Z, 0-9 i podkreślenie _
\W - dowolny znak nie będący znakiem słowa
\### - znak o kodzie podanym ósemkowo, np. \327
\x## - znak o kodzie podanym szesnastkowo, np. \x4b to wielka litera K
\x{####} - znak UNICODE, np. \x{20AC} to symbol Euro €


Klasy znaków

edytuj

Znaki można pogrupować w klasy, przy czym taka klasa odpowiada dowolnemu zna­kowi do niej należącemu. Klasę znaków zamyka się nawiasami kwadratowymi. Używa­jąc kreski - można wskazać zakres znaków. Aby dopisać do klasy znak „-" jako taki, należy użyć zapisu \-.

Przykłady:

[abc]       - oznacza jedną z liter a, b lub c
[a-z]       - dowolna mała litera
[a-zA-Z]    - dowolna litera
[ąćęłńóśżź] - dowolna mała polska litera
[0-9\-+]    - dowolna cyfra lub znak + lub -, inaczej można zapisać [\d\-+]
[^0-9]      - dowolny znak nie będący cyfrą (to samo co \D), użyliśmy znaku ^
              (zaprzeczenia logicznego klasy, musi być na pierwszej pozycji)

AutoIt zawiera pewną ilość klas predefiniowanych:

[[:alnum:]]  - dowolny znak alfanumeryczny, jak [0-9a-zA-Z]
[[:alpha:]]  - dowolna litera, jak [a-zA-Z]
[[:ascii:]]  - dowolny znak o kodzie 0-127
[[:blank:]]  - spacja lub tabulator
[[:cntrl:]]  - klawisz ctrl
[[:digit:]]  - dowolna cyfra dziesiętna, tak jak \d lub [0-9]
[[:graph:]]  - dowolny drukowalny znak, z wyjątkiem spacji
[[:lower:]]  - dowolna mała litera, jak [a-z]
[[:print:]]  - dowolny drukowalny znak, łącznie ze spacją
[[:punct:]]  - dowolny drukowalny znak, z wyjątkiem liter i cyfr
[[:space:]]  - dowolny biały znak z wyjątkiem VT (chr(11)), czym odróżnia się od \s
[[:upper:]]  - dowolna duża litera
[[:word:]]   - znak słowa, znaki alfanumeryczne a-z, A-Z, 0-9 i podkreślenie _, tak jak \w
[[:xdigit:]] - cyfra szesnastkowa, jak [0-9a-hA-H]

Każda klasa może być zaprzeczona znakiem ^, i tak:

[^[:alpha:]] - oznacza dowolny znak nie będący literą
[^[:ascii:]] - dowolny znak o kodzie większym od 127

Można też łączyć kilka klas w jedną:

[[:alpha:][:blank:]] - dowolna litera, spacja lub tabulator


Kwantyfikatory

edytuj

Kwantyfikatory określają, ile razy wzorzec ma być powtórzony. Oto pełny wykaz kwantyfikatorów:

{x}    - wzorzec powtórzony x razy
{x,}   - wzorzec powtórzony x lub więcej razy
{0,x}  - wzorzec powtórzony co najwyżej x razy
{x, y} - wzorzec powtórzony co najmniej x razy, lecz nie więcej niż y razy
*      - wzorzec powtórzony dowolną ilość razy (poczynając od 0)
+      - wzorzec powtórzony minimum 1 raz
?      - wzorzec powtórzony 1 raz lub wcale

Przykład:

\d{2}-\d{3} - wzorzec formalnej poprawności zapisu kodu pocztowego (format xx-xxx), inaczej można zapisać \d\d-\d\d\d

[0-3][0-9]\.[0-1][0-9]\.\d{4} - wzorzec formalnej poprawności zapisu daty (format dd.mm.rrrr), nie jest idealny bo za dobrą datę uzna np. 35.13.2011


Kwantyfikatory domyślnie są „zachłanne" (ang. "greedy"), czyli szukają dopasowania do możliwie największej ilości znaków, pasujących do wzorca wyrażenia regularnego np.:

wzorzec .*tak dopasuje się w tekście można tak i także inaczej do łańcucha można tak i tak.

Aby wymusić dopasowanie do najkrótszego możliwego łańcucha należy użyć kwantyfikatora "leniwego" (ang. "lazy"), uzyskujemy go wstawiając za kwantyfikatorem znak zapytania ?:

wzorzec .*?tak dopasuje się teraz do łańcucha można tak.

Można także globalnie zmienić zachłanność kwantyfikatorów za pomocą odpowiedniego modyfikatora (patrz punkt Modyfikatory).


Od wersji AutoIt 3.3.10.2 wprowadzono nowy typ kwantyfikatora, kwantyfikator "zaborczy" (ang. "possessive"). Uzyskuje się go poprzez wstawienie za kwantyfikatorem znaku plus +.

Kwantyfikator "zaborczy" sprawdza tylko dopasowanie całego tekstu, a nie także jego fragmentów (co ma miejsce w pozostałych typach kwantyfikatorów).

W tym wypadku wzorzec .*+tak nie znajdzie dopasowania w tekście można tak i także inaczej, natomiast znajdzie w tekście można tak i tak.


Alternatywne wzorce

edytuj

Czasami jest potrzebne stwierdzenie czy występuje dopasowanie z dowolnym wzorcem z pewnej ich grupy. Zamiast kolejno sprawdzać dopasowanie, możemy utworzyć wzorzec alternatywny.

Poszczególne wzorce łączy się z użyciem znaku pionowej kreski | (jest to odpowiednik operatora logicznego OR).

Przykładowo jeżeli za prawidłowe oznaczenie kodu pocztowego uznamy format xx-xxx lub xx.xxx, to nasz wzorzec może wyglądać tak:

\d{2}-\d{3}|\d{2}\.\d{3}

Często wzorce alternatywne umieszcza się w nawiasach, aby jasne było, gdzie taka alternatywa się zaczyna i gdzie się kończy, a także aby nie zostały do niej włączone przypadkowo znaki sąsiednie.

(\d{2}-\d{3}|\d{2}\.\d{3})

Alternatywy są sprawdzane od strony lewej do prawej, a użyta zostanie pierwsza zna­leziona możliwość.

UWAGA: W nawiasach kwadratowych znak | jest traktowany jako zwykły znak.


Asercje

edytuj

W wzorcach można użyć asercji, aby określić pewne warunki logiczne jakim powinno odpowiadać dopasowanie (np. w którym miejscu ma ono wystąpić). Wszystkie asercje mają zerową długość, co znaczy, że nie powodują wydłużenia dopasowanego tekstu.

Wykaz dostępnych asercji:

\b        - granica słowa (granicą słowa jest pierwszy znak nie będący literą, cyfrą lub znakiem podkreślenia _)
\B        - nie granica słowa
\A lub ^  - początek tekstu
\z lub $  - koniec tekstu
\Z        - koniec tekstu lub przed końcowym znakiem nowego wiersza
\G        - koniec poprzedniego dopasowania
Od wersji AutoIt 3.3.10.2:
(?=X)     - za dopasowaniem musi być podwzorzec X
(?!X)     - za dopasowaniem nie może być podwzorca X
(?<=X)    - przed dopasowaniem musi być podwzorzec X
(?<!X)    - przed dopasowaniem nie może być podwzorca X

Przykład z wzorcem kodu pocztowego miał pewną wadę. Dopasowywał się na przykład do łańcuch "A63-60000". Najczęściej nie o to nam chodzi, lecz oto czy sprawdzany tekst jest tylko i wyłącznie kodem pocztowym (np. czy to co zostało wpisane do formularza w rubryce o nazwie "Wpisz kod pocztowy:" jest rzeczywiście kodem pocztowym).

W tym celu możemy zmodyfikować nasz wzorzec z użyciem asercji:

\A\d{2}-\d{3}\z lub ^\d{2}-\d{3}$ - teraz dopasowanie nastąpi tylko wtedy gdy prawidłowy zapis kodu będzie jedynym składnikiem sprawdzanego łańcucha


Od wersji AutoIt 3.3.10.2 wprowadzono nowe asercje:

(?=X)     - za dopasowaniem musi być podwzorzec X
(?!X)     - za dopasowaniem nie może być podwzorca X
(?<=X)    - przed dopasowaniem musi być podwzorzec X
(?<!X)    - przed dopasowaniem nie może być podwzorca X

I tak wzorzec:

"numer(?=\d\d)" oznacza, że dopasowanie do "numer" nastąpi gdy po ciągu "numer" będą dwie cyfry,

"numer(?!acja)" oznacza, że dopasowanie do "numer" nastąpi gdy po ciągu "numer" nie będzie ciągu "acja",

"(?<=[[:alpha:]])ala" oznacza, że dopasowanie do "ala" nastąpi gdy przed ciągiem "ala" będzie dowolna litera,

"(?<![[:alpha:]])ala" oznacza, że dopasowanie do "ala" nastąpi gdy przed ciągiem "ala" nie będzie litery.

Modyfikatory

edytuj

Modyfikatory mają za zadanie zmianę sposobu interpretowania wzorca. Mają one następującą formę:

(?...) - gdzie ... oznaczają dodatkowe symbole i tak:

(?i)      - pominięcie rozróżniania wielkości liter
(?-i)     - odwołanie pominięcie rozróżniania wielkości liter (domyślnie)
(?i:...)  - modyfikator ?i odnosi się tylko do grupy znaków wymienionych po dwukropku, np. (?i:abc)
(?-i:...) - odwołanie powyższego modyfikatora
(?m)      - znaki ^ oraz $ wewnątrz danych pasują także do znaku nowego wiersza 
(?-m)     - odwołanie (?m) (domyślnie)
(?s)      - kropka oznacza dowolny znak, także nowego wiersza
(?-s)     - kropka oznacza dowolny znak, z wyjątkiem nowego wiersza (domyślnie)
(?x)      - ignorowanie białych znaków
(?-x)     - odwołanie ignorowania białych znaków (domyślnie)
(?U)      - kwantyfikatory niezachłanne
(?-U)     - kwantyfikatory zachłanne (domyślnie)


Grupowanie znaków i odwołania wsteczne

edytuj

We wzorcu znaki można grupować umieszczając je wewnątrz zwykłych nawiasów (). Taka grupa jest traktowana jako całość i np. wstawiony po niej kwantyfikator odnosi się do całej grupy, a nie tylko do pojedynczego znaku np.:

(ab)+

Grupowanie może zmienić sposób interpretowania wzorca np.:

^aaa|bbb$ - oznacza że łańcuch zaczyna się od aaa, lub kończy na bbb

^(aaa|bbb)$ - łańcuch to "aaa" lub "bbb"

Możemy też ograniczyć zasięg działania alternatywy:

mo(ż|rz)e - dopasuje się do łańcucha "może" jak i "morze"


Ponadto grupowanie umożliwia użycie odwołań wstecznych.

Nawiasy mają zdolność zapamiętywania określonych fragmentów wzorca w celu ponownego odwołania się do niego w dalszej części wyrażenia. Do fragmentów tych dociera się poprzez odwołania: \1, \2, \3, itd. Odwołanie \1 dotyczy wyrażenia w pierwszej parze nawiasów, \2 - w drugiej, itd. Jest to odpowiednik zmiennej wewnątrz wzorca.

Przykład:

^([a-z]{2})[a-z]*\1$ - wzorzec ten dopasowuje się do wyrazów zaczynających się i kończących tymi samymi dwiema literami, np.: mama, magma, kasetka itp.

Zwróćmy uwagę, że odwołanie wsteczne nie zapamiętuje postaci wzorca lecz dopasowanie odpowiadające temu wzorcowi. To dopasowanie jest wzorcem w miejscu wywołania wstecznego. Prześledźmy to na przykładzie dopasowania do słowa magma.

Wzorzec ([a-z]{2}) dopasowuje się do dwóch pierwszych liter słowa "magma" i jednocześnie nadaje odwołaniu \1 wartość równą tym dwóm literom ("ma"), w miejscu wywołania \1 wstawia do wzorca litery "ma". Nasz wzorzec zadziała tak jak gdyby miał postać ([a-z]{2})[a-z]*(ma), a nie jak ([a-z]{2})[a-z]*([a-z]{2}).


UWAGA:

Wywołanie grupy typu \n (gdzie n to nr grupy) ma pewną wadę, która może niekiedy prowadzić do błędów. Jeżeli we wzorcu nie będzie grupy o podanym numerze, to zapis \n zostanie potraktowany jako znak o kodzie n (w zapisie ósemkowym).

W związku z tą niejednoznacznością bezpieczniej będzie użyć wywołania \gn lub jeszcze lepiej \g{n} (np. \g5 lub \g{5}).


Zapamiętywanie dopasowań

Istnieje możliwość odwołania się do zapamiętanej za pomocą nawiasów wartości także poza samym wyrażeniem regularnym, a mianowicie w argumencie funkcji StringRegExpReplace. Odpowiednikami odwołań \1, \2,... poza wzorcem są odpowiednio zmienne $1, $2, ...


Grupy nazwane

edytuj

Grupy nazwane to po prostu grupy przechwytywania wraz ze zdefiniowanymi nazwami. Dostęp do takich grup odbywa się poprzez ich nazwy, a nie numery.

(?<nazwa_grupy> ... )

Odwołanie do grupy nazwanej:

\k<nazwa_grupy>

lub:

\k'nazwa_grupy'

ewentualnie:

\k{nazwa_grupy}

Dla przykładu wzorzec dopasowują się do wyrazów zaczynających się i kończących tymi samymi dwiema literami, z użyciem grupy nazwanej może wyglądać tak:

^(?<dwie_litery>[a-z]{2})[a-z]*\k<dwie_litery>$


Grupy nieprzechwytujące (ang. non-capturing groups)

edytuj

Od wersji AutoIt 3.3.10.2 wprowadzono nowy rodzaj grupowania, w grupy nieprzechwytujące. Takie grupy nie są zapamiętywane i nie są numerowane. Możemy więc oddzielić to co chcemy zapamiętać, od tego co chcemy tylko odpowiednio uporządkować.

Jest oczywistym, że grup tych nie można wykorzystywać w odwołaniach wstecznych.

(?: ... ) - grupa nieprzechwytująca (zwykła)

Cała grupa łącznie z wszystkimi wewnętrznymi nawiasami nie jest zapamiętana i numerowana.

(?| ... ) - grupa nieprzechwytująca z resetem (Branch Reset)

W tym przypadku cała grupa otrzymuje numer, ale nie nawiasy znajdujące się wewnątrz grupy (te nawiasy nie są przechwytywane, zapamiętana jest tylko grupa jako całość, np. (?|A(\d+)|(\d+)B|C(\d+)D)).

(?> ... ) - grupa niepodzielna

Inny rodzaj grupy nieprzechwytującej to tak zwana grupa niepodzielna (atomic group). Normalnie silnik obsługujący wyrażenia regularne obsługuje tzw. sprawdzanie wsteczne (backtracking). Grupa niepodzielna powoduje wyłączenie sprawdzania wstecznego, ale tylko w odniesieniu do części wyrażenia ujętej we wnętrzu grupy niepodzielnej. Prześledźmy to na poniższych przykładach pokazujących różnice między grupą nieprzechwytującą zwykłą i grupą niepodzielną.

$kod="ABC"
If StringRegExp($kod,"(?:A|.B)C") Then
   MsgBox(0,"Test","Kod jest prawidłowy!")
Else
   MsgBox(0,"Test","Kod jest nieprawidłowy!")
Endif

Najpierw sprawdzane jest czy pierwszą litera jest A, ponieważ jest to prawdą to drugą literą powinno być C. Ponieważ nie jest, nie ma dopasowania z wzorcem. Teraz badanie powraca do drugiej części alternatywnego wzorca i jest sprawdzane czy drugą literą jest B. Jest to prawda więc sprawdzane jest czy trzecią literą jest C. To też jest prawdziwe więc ostatecznie dopasowanie zostanie wykryte (zostanie wyświetlony komunikat "Kod jest prawidłowy!"). A teraz przykład z grupą niepodzielną:

$kod="ABC"
If StringRegExp($kod,"(?>A|.B)C") Then
   MsgBox(0,"Test","Kod jest prawidłowy!")
Else
   MsgBox(0,"Test","Kod jest nieprawidłowy!")
Endif

Tym razem po sprawdzeniu pierwszej części alternatywnego wzorca, badanie nie powróci do sprawdzanie jego drugiej części i dopasowanie nie zostanie wykryte (zostanie wyświetlony komunikat "Kod jest nieprawidłowy!"). Druga część alternatywnego wzorca będzie sprawdzana tylko wtedy, gdy pierwsza nie będzie dopasowana. Ma to niekiedy znaczenie dla poprawy wydajności. Wyobraźmy sobie, że chcemy znaleźć sekwencję AC lub BC. Dla takiego przypadku wzorzec (?:A|B)C jest nieoptymalny, gdyż sprawdzanie drugiej części alternatywy nie ma sensu, gdy pierwsza daje dopasowanie (jeżeli pierwszą literą jest A, to na pewno nie będzie B). Optymalnym wzorcem będzie więc (?>A|B)C.

(?# ... ) - komentarz, grupa jest ignorowana, np.: (?# to jest komentarz)


Inne nowości w wersji 3.3.10.2 AutoIt'a

edytuj

AutoIt wykorzystuje do obsługi wyrażeń regularnych silnik PCRE (Perl-Compatible Regular Expressions). Implementacja ta zawiera UPC (Unicode Category Properties), co pozwala na wsparcie przetwarzania większości używanych na świecie języków.

Jednakże, aby zachować zgodność z poprzednimi wersjami i utrzymać wysoką prędkość przetwarzania, wsparcie UCP nie jest domyślnie włączona . Można ją włączyć przez poprzedzenie wstawienie ciągu znaków (*UCP) na samym początku wyrażenia regularnego.


Nowe znaki specjalne

edytuj

W związku z obsługą UCP wprowadzono nowe znaki specjalne:

\p{xxx} - znak posiada własność xxx
\P{xxx} - znak nie posiada własności xxx

Rozpoznawane własności:

{L}  - dowolna litera, także polska
[Ll} - dowolna mała litera
{Lu} - dowolna duża litera
{Sc} - symbol waluty
{NazwaBlokuUnicode} - znak UNICODE z określonego bloku (np. Latin, Greek, Cyrillic, Arabic, itp.)


Ustawienia globalne

edytuj

Domyślną wartością dla \N jest jeden ze znaków: @CR, @LF, lub sekwencja @CRLF. Można to zmienić wstawiając na początku wyrażenia:

(*CR)      - tylko znak powrotu karetki (jak @CR)
(*LF)      - tylko znak nowego wiersza (jak @LF)
(*CRLF)    - tylko sekwencja CRLF (jak @CRLF)
(*ANYCRLF) - każdy ze znaków @CR, @LF, lub sekwencja @CRLF (wartość domyślna)
(*ANY)     - dowolna sekwencja nowej linii Unicode: CRLF, LF, VT, FF, CR lub \x85

Domyślną wartością dla \R jest jeden ze znaków: @CR, @LF, lub sekwencja @CRLF. Można to zmienić wstawiając na początku wyrażenia:

(*BSR_ANYCRLF) - każdy ze znaków @CR, @LF, lub sekwencja @CRLF (wartość domyślna)
(*BSR_UNICODE) - dowolna sekwencja nowej linii Unicode: CRLF, LF, VT, FF, CR lub \x85

Możliwe jest ograniczenie maksymalnej ilości szukanych dopasowań, oraz zagłębień rekurencyjnych do określonej liczby:

(*LIMIT_MATCH=n)     - gdzie n to maksymalna liczba dopasowań
(*LIMIT_RECURSION=n) - gdzie n to maksymalna liczba zagłębień


Wykorzystanie wyrażeń regularnych w skryptach AutoIt

edytuj

Do tej pory omawialiśmy ogólne zasady tworzenia wyrażeń regularnych. Zdobytą wiedzę możemy wykorzystać nie tylko w skryptach AutoIt'a, ale także w każdym innym programie posiadającym obsługę wyrażeń regularnych. Będzie to większość nowoczesnych języków programowania, środowisk programistycznych, edytorów tekstu itp.

Zajmijmy się teraz wykorzystaniem wyrażeń regularnych w skryptach AutoIt'a. Służą do tego dwie funkcje StringRegExp i StringRegExpReplace.

Pierwsza wyszukuje dopasowania w testowanym łańcuchu, druga dokonuje jego przetworzenia zgodnie z regułami opisanymi wyrażeniem regularnym.

StringRegExp ( "tekst", "wzorzec" [, flag ] [, offset ] ] )

Funkcja sprawdza czy łańcuch pasuje do danego wzorca wyrażenia regularnego.

"tekst" - string do sprawdzenia

"wzorzec" - wyrażenie regularne do porównania

flag - flaga określająca jaką wartość będzie zwracać funkcja

0 - zwraca True (1) gdy znaleziono dopasowane lub False (0) jeżeli nie znaleziono (domyślne)

1 - zwraca pierwsze dopasowanie w postaci tablicy wyników

2 - zwraca pierwsze dopasowanie w postaci tablicy (styl Perl'a)

3 - zwraca tablicę wszystkich dopasowań

4 - zwraca tablicę tablic wszystkich dopasowań (styl Perl'a)


UWAGA: Wyniki otrzymane dla flag=1 i flag=2 są użyteczne tylko wtedy, gdy we wzorcu nie ma grupowania znaków z użyciem nawiasów. Jeżeli są to zamiast dopasowania do całego wzorca otrzymamy dopasowania do fragmentów ujętych w nawiasy (czyli wartości zmiennych $1, $2 ... zapamiętanych wzorców). Z tego powodu nie polecam używania tej opcji.

Pełną informację o dopasowaniach daje tylko rezultat otrzymany dla flag=4. Niestety jego forma jest dość skomplikowana dlatego postaram się pokrótce ją opisać.

Wynik działania funkcji StringRegExp jest jednowymiarową tablicą, której elementami są inne jednowymiarowe tablice (nazwijmy je podtablicami).

Tablica zawiera tyle elementów (podtablic) ile jest dopasowań do całego wzorca (funkcja UBound zwróci więc ilość dopasowań w całym sprawdzanym łańcuchu).

Podtablice w elemencie [0] zawierają string dopasowania do pełnego wzorca, w kolejnych elementach [1], [2], ... zawarte są dopasowania do części wzorca ujętego w nawiasy (), poczynając od najbardziej zewnętrznej pary nawiasów. Jeżeli pary nawiasów są równorzędne, to kolejność jest od lewej do prawej.

Wartości te odpowiadają wartościom zmiennych zapamiętanych dopasowań $1, $2, ... Ponieważ najczęściej potrzebujemy informacje jedynie o dopasowaniach do pełnego wzorca, warto napisać własną funkcję, która nam to ułatwi. Przykład takiej funkcji znajduje się w rozwiązaniu ćwiczenia nr 4.


Zwracana wartość (dodatkowa):

dla flag=0

@Error=2 - zły wzorzec; @Extended=położenie_błędu_we_wzorcu

dla flag=1 lub 2

@Error=0 - tablica jest prawidłowa

@Error=1 - tablica jest nieprawidłowa, brak dopasowania

@Error=2 - zły wzorzec; @Extended=położenie_błędu_we_wzorcu

dla flag=3 lub 4

@Error=0 - tablica jest prawidłowa

@Error=1 - tablica jest nieprawidłowa, brak dopasowania

@Error=2 - zły wzorzec; @Extended=położenie_błędu_we_wzorcu

offset - od którego znaku łańcuch poszukiwane jest dopasowanie do wzorca (domyślnie 1, czyli od początku)


Przykład (skrypt sprawdzający czy zmienna zawiera prawidłowy kod pocztowy):

$sKod = "63-600"
If StringRegExp($sKod, "^\d{2}-\d{3}$") Then
   MsgBox(0, "Test", "Kod jest prawidłowy!")
Else
   MsgBox(0, "Test", "Kod jest nieprawidłowy!")
EndIf


StringRegExpReplace ( "tekst", "wzorzec", "podmiana", [ count ] )

Funkcja zwraca łańcuch powstały z zamiany pasującego do wzorca fragment łańcucha "tekst", na łańcuch "podmiana".

"tekst" - string do przetworzenia

"wzorzec" - wyrażenie regularne do porównania

"podmiana" - string na który zostanie podmieniony fragment stringu "tekst", można korzystać z zapamiętanych w zmiennych $1, $2,... dopasowań (patrz p.8. Grupowanie znaków i odwołania wsteczne)

UWAGA: Jeżeli po zapamiętanym dopasowaniu chcemy wstawić cyfrę to numer zmiennej należy ująć w nawiasy klamrowe, np.: ${2}5

count - określa ile dopasowań ma być zamienione (domyślnie 0, czyli wszystkie)

Funkcja dodatkowo zwraca w makrze @Error:

0 - sukces, w makrze @Extended ilość podmian

2 - nieprawidłowy wzorzec, w makrze @Extended położenie błędu we wzorcu

Przykład 1 (zamiana w tekście polskich liter na gwiazdki *):

$sTxt1 = "żółci się na łące"                     ;przykładowy tekst do zamiany
$sWR = "[ąćęłńóśżź]"                             ;nasz wzorzec wyrażenia regularnego
$sTxt2 = StringRegExpReplace($sTxt1, $sWR, "*")  ;zamiana na *
MsgBox(0, "Test", $sTxt2)                        ;i wyświetlenie rezultatu, ***ci si* na **ce


Przykład 2 (przestawienie pierwszego znaku w łańcuchu na jego koniec) - użycie zapamiętywania dopasowań:

$sTxt1 = "AutoIt"                                  ;przykładowy tekst do zamiany
$sWR = "^(.)(.*)"                                  ;nasz wzorzec wyrażenia regularnego
$sTxt2 = StringRegExpReplace($sTxt1, $sWR, "$2$1") ;zamiana z użyciem zapamiętanych dopasowań
MsgBox(0, "Test", $sTxt2)                          ;i wyświetlenie rezultatu, utoItA


Ćwiczenia

edytuj

1. Napisać skrypt sprawdzający czy podany string jest prawidłową (pod względem formalnym) ścieżką dostępu do pliku.

2. Napisać skrypt dzielący dany tekst na pojedyncze słowa. Separatorem słów są białe znaki.

3. Zamienić amerykański zapis dowolnej daty (mm-dd-rrrr) na zapis w formacie europejskim (rrrr.mm.dd).

4. Napisać skrypt wyszukujący we wczytanym z dysku pliku tekstowym wszystkie słowa zaczynające się i kończące na te same dwie litery.

Przykładowe rozwiązania: AutoIt/Ćwiczenia dla zaawansowanych - przykładowe rozwiązania