Darmowy fragment publikacji:
IDZ DO
IDZ DO
PRZYK£ADOWY ROZDZIA£
PRZYK£ADOWY ROZDZIA£
SPIS TRE(cid:140)CI
SPIS TRE(cid:140)CI
KATALOG KSI¥flEK
KATALOG KSI¥flEK
KATALOG ONLINE
KATALOG ONLINE
ZAM(cid:211)W DRUKOWANY KATALOG
ZAM(cid:211)W DRUKOWANY KATALOG
TW(cid:211)J KOSZYK
TW(cid:211)J KOSZYK
DODAJ DO KOSZYKA
DODAJ DO KOSZYKA
CENNIK I INFORMACJE
CENNIK I INFORMACJE
ZAM(cid:211)W INFORMACJE
ZAM(cid:211)W INFORMACJE
O NOWO(cid:140)CIACH
O NOWO(cid:140)CIACH
ZAM(cid:211)W CENNIK
ZAM(cid:211)W CENNIK
CZYTELNIA
CZYTELNIA
FRAGMENTY KSI¥flEK ONLINE
FRAGMENTY KSI¥flEK ONLINE
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Wyra¿enia regularne
Autor: Jeffrey E. F. Friedl
T‡umaczenie: Adam Podstawczyæski
ISBN: 83-7197-351-9
Tytu‡ orygina‡u:
Format: B5, stron: 320
Mastering Regular Expressions
Wyra¿enia regularne to niezwykle skuteczny mechanizm przetwarzania tekst(cid:243)w
i(cid:160) innych danych. Ci, kt(cid:243)rzy do tej pory nie zetknŒli siŒ z tym pojŒciem, odkryj„ dziŒki tej
ksi„¿ce nowe, potŒ¿ne narzŒdzia, pozwalaj„ce w pe‡ni zapanowa(cid:230) nad danymi.
Prezentowana tu wiedza jest tak szczeg(cid:243)‡owa i obszerna, ¿e nawet komputerowi
weterani znajd„ co(cid:156) nowego dla siebie.
UmiejŒtne stosowanie wyra¿eæ regularnych pozwala radykalnie upro(cid:156)ci(cid:230) przetwarzanie
wszelkiego rodzaju informacji, poczynaj„c od poczty elektronicznej, poprzez pliki
dziennik(cid:243)w a¿ do dokument(cid:243)w tekstowych. Mechanizm ten odgrywa niezwykle wa¿n„
rolŒ w programowaniu skrypt(cid:243)w CGI, czŒsto przetwarzaj„cych rozmaite dane tekstowe.
Wyra¿enia regularne nie funkcjonuj„ samodzielnie. Opr(cid:243)cz doskonale wszystkim
znanego programu grep, wchodz„ one w sk‡ad takich narzŒdzi programisty, jak:
translatory jŒzyk(cid:243)w skryptowych (m.in. Perl, Tcl, awk i Python),
edytory tekst(cid:243)w (Emacs, vi, Nisus Writer i inne),
(cid:156)rodowiska programowania (m.in. Delphi i Visual C++)
inne wyspecjalizowane narzŒdzia (np. lex, Expert czy sed).
Korzystanie z wyra¿eæ regularnych wymaga nie tylko wiedzy teoretycznej, ale r(cid:243)wnie¿
znajomo(cid:156)ci pewnych niuans(cid:243)w. Jeffrey Friedl konsekwentnie prowadzi nas przez
kolejne etapy tworzenia konstrukcji, kt(cid:243)re dok‡adnie zrealizuj„ wszystkie postawione
przed nimi zadania.
Wyra¿enia regularne nie istniej„ oczywi(cid:156)cie same dla siebie. Na stronach ksi„¿ki
przedstawiono liczne przyk‡ady wykorzystuj„cych je narzŒdzi, a tak¿e wiele
praktycznych przyk‡ad(cid:243)w. Szczeg(cid:243)lnie du¿o uwagi po(cid:156)wiŒcono jŒzykowi Perl,
wyposa¿onemu w bogaty zestaw funkcji przeznaczonych specjalnie do obs‡ugi
wyra¿eæ regularnych.
Zawarte w tej ksi„¿ce porady pozwol„ Czytelnikom unikn„(cid:230) wszelkich pu‡apek
i(cid:160) skutecznie wykorzysta(cid:230) mo¿liwo(cid:156)ci wyra¿eæ regularnych.
(cid:132)Ksi„¿ka by‡a dla mnie tyle¿ przyjemna, co pouczaj„ca, nawet w kwestiach
zwi„zanych z Perlem(cid:148)
Tom Christiansen, wsp(cid:243)‡autor ksi„¿ki Perl. Programowanie
6/.3;+
463;+./2/.3;6+
/q6/19+62-
Rozwiązywanie prawdziwych problemów...................................................e........................... 18
Wyrażenia regularne jako język ...................................................e........................................... 19
Analogia do nazw plików...................................................e............................................. 19
Analogia do języka...................................................e...................................................e.... 20
Myślenie wyrażeniami regularnymi ...................................................e..................................... 21
Przeszukiwanie plików tekstowych — egrep ...................................................e.............. 22
Metaznaki programu egrep ...................................................e...................................................e 23
Początek i koniec wiersza ...................................................e............................................ 23
Klasy znaków ...................................................e...................................................e............ 23
Kropka, czyli dowolny znak ...................................................e........................................ 26
Alternacja ...................................................e...................................................e.................. 27
Granice słów...................................................e...................................................e.............. 28
W skrócie...................................................e...................................................e................... 29
Elementy opcjonalne...................................................e...................................................e. 30
Inne kwantyfikatory — powtarzanie...................................................e............................ 31
Ignorowanie wielkości znaków...................................................e.................................... 33
Nawiasy i odwołania wsteczne ...................................................e.................................... 33
Szybki unik...................................................e...................................................e................ 35
Ponad podstawy ...................................................e...................................................e................. 35
Różnorodność językowa ...................................................e.............................................. 35
Cel tworzenia wyrażenia regularnego...................................................e.......................... 35
Jeszcze kilka przykładów...................................................e............................................. 36
Terminologia wyrażeń regularnych ...................................................e............................. 38
Podwyższanie kwalifikacji...................................................e........................................... 40
Podsumowanie ...................................................e...................................................e.......... 42
Uwagi osobiste...................................................e...................................................e................... 43
6/.3;+
6o+.;6+
/q6/19+62-
O przykładach ...................................................e...................................................e.................... 45
Perl — krótkie wprowadzenie...................................................e...................................... 46
Wyszukiwanie tekstu za pomocą wyrażeń regularnych...................................................e....... 48
Przykład bliższy rzeczywistości...................................................e................................... 49
Skutki uboczne udanego dopasowania ...................................................e........................ 50
Przeplatanie wyrażeń regularnych ...................................................e............................... 53
Chwila odpoczynku...................................................e...................................................e... 56
Modyfikowanie znalezionego tekstu ...................................................e.................................... 57
Edycja zautomatyzowana...................................................e............................................. 60
Proste przetwarzanie wiadomości e-mailowych ...................................................e.......... 61
I znów powtarzające się słowa...................................................e..................................... 66
6/1.092-3.+2;6+
/q6/19+62-
Spacerkiem po krainie wyrażeń regularnych...................................................e........................ 72
Świat według grepa ...................................................e...................................................e... 72
Czas wszystko zmienia ...................................................e................................................ 73
Najkrótszy przegląd ...................................................e...................................................e........... 74
POSIX ...................................................e...................................................e....................... 76
„Otoczka” wyrażeń regularnych...................................................e........................................... 77
Identyfikacja wyrażenia regularnego ...................................................e........................... 78
Operacje na dopasowanym tekście ...................................................e.............................. 78
Inne przykłady...................................................e...................................................e...........79
„Otoczka” wyrażeń regularnych — podsumowanie...................................................e.... 81
Silniki a błyszczący lakier ...................................................e.................................................... 82
Lakier ...................................................e...................................................e........................ 82
Silnik i kierowca..................................e...................................................e.........................82
Typowe metaznaki...................................................e...................................................e............. 82
Skróty znakowe ...................................................e...................................................e......... 83
Łańcuchy jako wyrażenia regularne...................................................e............................. 86
Skrótowy zapis klas, kropka i klasy znaków ...................................................e............... 88
Zakotwiczanie ...................................................e...................................................e........... 92
Grupowanie i wydobywanie informacji...................................................e....................... 94
Kwantyfikatory...................................................e...................................................e.......... 94
Alternacja ...................................................e...................................................e.................. 95
Przewodnik po dalszych rozdziałach...................................................e.................................... 95
Informacje specyficzne dla konkretnego narzędzia ...................................................e..... 96
/-+2+46/8;+6+2+;6+
/q
Przekręcamy klucz w stacyjce ...................................................e.............................................. 97
Dwa typy silników ...................................................e...................................................e.... 97
Nowe standardy...................................................e...................................................e......... 98
Typy mechanizmów wyrażeń regularnych ...................................................e.................. 98
Kilka dodatkowych pytań ...................................................e.......................................... 100
Podstawy dopasowywania ...................................................e.................................................. 100
O przykładach ...................................................e...................................................e......... 100
Zasada 1. Najwcześniejsze dopasowanie wygrywa...................................................e... 101
6/.3;+
Skrzynia biegów...................................................e...................................................e...... 102
Części silnika...................................................e...................................................e...........102
Zasada 2. Niektóre metaznaki są „zachłanne” ...................................................e........... 103
Sterowanie wyrażeniem a sterowanie tekstem ...................................................e................... 108
Mechanizm NFA — sterowanie wyrażeniem...................................................e............ 108
Mechanizm DFA — sterowanie tekstem ...................................................e................... 109
Wyjaśnienie „zagadki istnienia” ...................................................e................................ 110
Wycofywanie ...................................................e...................................................e................... 111
„Krucha” analogia ...................................................e...................................................e... 111
Dwie istotne sprawy dotyczące wycofywania ...................................................e........... 112
Zachowane stany ...................................................e...................................................e..... 113
Wycofywanie a zachłanność ...................................................e...................................... 114
Więcej o zachłanności ...................................................e...................................................e..... 117
Problemy z zachłannością ...................................................e.......................................... 117
„Cudzysłowy” wieloznakowe ...................................................e.................................... 118
Lenistwo? ...................................................e...................................................e................118
Zachłanność zawsze sprzyja dopasowaniu ...................................................e................ 119
Czy alternacja jest zachłanna? ...................................................e................................... 120
Sposoby wykorzystania alternacji niezachłannej...................................................e....... 121
Alternatywa zachłanna z perspektywy...................................................e....................... 123
Klasy znaków a alternacja...................................................e.......................................... 123
NFA, DFA i POSIX...................................................e...................................................e.........123
„Najdłuższe najbardziej z lewej” ...................................................e............................... 123
POSIX a zasada „najdłuższe najbardziej z lewej” ...................................................e..... 125
Szybkość i wydajność ...................................................e................................................ 126
Porównanie mechanizmów DFA i NFA ...................................................e.................... 126
Techniki tworzenia wyrażeń regularnych...................................................e........................... 128
O czym należy pamiętać ...................................................e............................................ 129
Warto być konkretnym...................................................e............................................... 130
Trudności i niemożliwości ...................................................e......................................... 133
Uwaga na niepożądane dopasowania...................................................e......................... 134
Dopasowanie ograniczonego tekstu...................................................e........................... 136
Wiedza o przetwarzanych danych...................................................e.............................. 139
Dalsze przykłady zachłanności ...................................................e.................................. 139
Podsumowanie...................................................e...................................................e................. 142
Podsumowanie mechaniki dopasowania...................................................e.................... 142
Praktyczne efekty działania mechanizmów dopasowania wzorca................................ 143
346+-3;;+2/;6+
/q6/19+62-
Przykład otrzeźwiający...................................................e...................................................e.... 146
Prosta zmiana — najlepszą chorągiew posyłamy przodem.......................................... 146
Krok dalej: znalezienie źródła zachłanności...................................................e.............. 147
Twarda rzeczywistość ...................................................e................................................ 149
O wycofywaniu ogólnie...................................................e...................................................e... 151
POSIX NFA — więcej pracy...................................................e..................................... 152
Gdy nie ma dopasowania ...................................................e........................................... 152
Dążenie do precyzji...................................................e...................................................e. 153
Alternacja może kosztować...................................................e........................................ 154
6/.3;+
Silne prowadzenie ...................................................e...................................................e... 155
Wpływ nawiasów okrągłych ...................................................e...................................... 155
Optymalizacja wewnętrzna...................................................e................................................. 159
Rozpoznawanie pierwszego znaku ...................................................e............................ 159
Sprawdzanie obecności stałego fragmentu tekstu...................................................e...... 160
Proste powtarzanie ...................................................e...................................................e.. 160
Niepotrzebne małe kwantyfikatory ...................................................e............................ 162
Rozpoznanie długości ...................................................e................................................ 162
Rozpoznanie dopasowania ...................................................e......................................... 162
Rozpoznanie potrzeb...................................................e.................................................. 162
Zakotwiczenia łańcucha lub wiersza...................................................e.......................... 162
Buforowanie postaci skompilowanej ...................................................e......................... 163
Identyfikacja mechanizmu...................................................e.................................................. 165
NFA czy DFA?...................................................e...................................................e........ 165
NFA tradycyjny czy posiksowy? ...................................................e............................... 166
Rozwijanie pętli ...................................................e...................................................e............... 166
Metoda pierwsza: tworzenie wyrażenia na podstawie doświadczenia ......................... 167
Faktyczny wzór na „rozwinięcie pętli” ...................................................e...................... 168
Metoda druga: pogląd z góry ...................................................e..................................... 171
Metoda trzecia: nazwa hosta internetowego w cudzysłowach ..................................... 171
Obserwacje ...................................................e...................................................e.............. 172
Rozwijanie komentarzy w C...................................................e............................................... 173
Wyrażeniowy zawrót głowy ...................................................e...................................... 173
Sposób naiwny ...................................................e...................................................e........ 173
Rozwijanie pętli w języku C ...................................................e...................................... 176
Swobodne wyrażenie ...................................................e...................................................e.......177
Dopasowanie wspomagane ...................................................e........................................ 177
Czy można jeszcze szybciej? ...................................................e..................................... 178
Opakowanie...................................................e...................................................e............. 180
Nic nie zastąpi myślenia ...................................................e...................................................e.. 181
Różne oblicza optymalizacji ...................................................e...................................... 181
326/82-2+6).+-
Pytania, które powinny się pojawić...................................................e.................................... 185
Pozornie prosty grep… ...................................................e.............................................. 185
W tym rozdziale ...................................................e...................................................e...... 187
Język awk...................................................e...................................................e......................... 187
Różnice pomiędzy odmianami wyrażeń regularnych w awku ..................................... 188
Funkcje i operatory wyrażeń regularnych w awku ...................................................e.... 190
Tcl ...................................................e...................................................e.................................... 192
Argumenty wyrażeń regularnych...................................................e............................... 192
Korzystanie z wyrażeń regularnych Tcl-a...................................................e.................. 193
Optymalizacja wyrażeń w języku Tcl ...................................................e........................ 195
GNU Emacs ...................................................e...................................................e..................... 195
Łańcuchy Emacsa jako wyrażenia regularne ...................................................e............. 196
Emacsowa odmiana wyrażeń regularnych...................................................e................. 197
Wyniki dopasowania w Emacsie ...................................................e............................... 199
6/.3;+
Pomiar wydajności w Emacsie...................................................e................................... 200
Optymalizacja wyrażeń regularnych w Emacsie ...................................................e....... 201
6+
/2+6/19+62/ /6+
Metoda Perla ...................................................e...................................................e.................... 204
Wyrażenia regularne jako składnik języka ...................................................e................ 205
Największa siła Perla ...................................................e................................................. 206
Największa słabość Perla ...................................................e........................................... 207
Perl a problem jajka i kury ...................................................e......................................... 207
Przykład wprowadzający: analiza tekstu w formacie CSV .......................................... 208
Wyrażenia regularne a metoda Perla...................................................e.......................... 210
Perl bez tajemnic ...................................................e...................................................e..... 211
„Perlizmy” związane z wyrażeniami regularnymi ...................................................e............. 212
Kontekst wyrażenia regularnego...................................................e................................ 213
Zasięg dynamiczny a wynik dopasowania...................................................e................. 214
Zmienne specjalne po dopasowaniu...................................................e........................... 219
„Przetwarzanie cudzysłowowe” i interpolacja zmiennych ........................................... 221
Perlowa odmiana wyrażeń regularnych...................................................e.............................. 226
Kwantyfikatory zachłanne i leniwe...................................................e............................ 226
Grupowanie ...................................................e...................................................e............. 228
Punkty zakotwiczenia łańcucha ...................................................e................................. 233
Zakotwiczenie poprzedniego dopasowania ...................................................e............... 237
Punkty zakotwiczenia słów ...................................................e........................................ 241
Wygodne skróty i inne sposoby notacji ...................................................e..................... 242
Klasy znaków ...................................................e...................................................e.......... 244
Prawdziwe kłamstwa, czyli modyfikacja z użyciem symbolu e\Q
i znaków pokrewnych ...................................................e................................................ 246
Operator dopasowania ...................................................e...................................................e.....247
Ograniczniki argumentu dopasowania...................................................e....................... 247
Modyfikatory dopasowania...................................................e........................................ 249
Określanie argumentu docelowego ...................................................e............................ 250
Inne efekty uboczne operatora dopasowania ...................................................e............. 251
Wartość zwracana przez operator dopasowania ...................................................e........ 252
Czynniki zewnętrzne wpływające na operator dopasowania........................................ 254
Operator podstawiania ...................................................e...................................................e..... 255
Argument podstawienia ...................................................e............................................. 255
Modyfikator /e...................................................e...................................................e......... 256
Kontekst i wartość zwracana...................................................e...................................... 258
Użycie modyfikatora /g w wyrażeniu, które może dopasować „nic”........................... 258
Operator split ...................................................e...................................................e................... 259
Podstawowe działanie operatora split ...................................................e........................ 259
Zaawansowane działanie operatora split...................................................e.................... 260
Zaawansowany argument dopasowania w split ...................................................e......... 261
Operator split w kontekście skalarnym...................................................e...................... 263
Argument dopasowania operatora split a nawiasy przechwytujące ............................. 263
Aspekty wydajności...................................................e...................................................e......... 264
„Jest na to wiele sposobów”...................................................e....................................... 265
Kompilacja wyrażenia, modyfikator /o i wydajność ...................................................e. 266
6/.3;+
Nietowarzyska zmienna $ i spółka...................................................e.......................... 271
Spadek wydajności wywołany modyfikatorem /i ...................................................e...... 277
Aspekty wydajności związane z podstawianiem ...................................................e....... 279
Testowanie ...................................................e...................................................e.............. 281
Usuwanie błędów wyrażenia regularnego ...................................................e................. 282
Funkcja study ...................................................e...................................................e.......... 284
Składamy wszystkie klocki...................................................e................................................. 286
Usuwanie końcowych i początkowych białych znaków............................................... 287
Dodawanie przecinków do liczb ...................................................e................................ 288
Usuwanie komentarzy z kodu w języku C...................................................e................. 288
Dopasowanie adresu poczty elektronicznej ...................................................e............... 289
Kilka słów na koniec...................................................e.................................................. 299
Uwagi na temat Perla4 ...................................................e............................................... 300
2036+-/.378)42/;7/-
Informacje ogólne...................................................e...................................................e............ 303
Rzemiosło wyrażeń regularnych ...................................................e................................ 303
O’Reilly Associates...................................................e................................................ 303
Wirtualna biblioteka oprogramowania OAK...................................................e............. 304
Archiwum GNU ...................................................e...................................................e...... 304
Yahoo!...................................................e...................................................e..................... 304
Inne adresy...................................................e...................................................e....................... 304
Awk ...................................................e...................................................e......................... 304
Pakiety biblioteczne dla języka C ...................................................e.............................. 304
Klasa wyrażeń regularnych Javy...................................................e................................ 304
Egrep ...................................................e...................................................e....................... 305
Emacs ...................................................e...................................................e...................... 305
Perl ...................................................e...................................................e.......................... 305
Python...................................................e...................................................e...................... 305
Tcl...................................................e...................................................e............................ 305
6316+.33,7o91+.6/71;/2+
#478+,/
9836/
#363;.
Przypomnijmy sobie problem powtórzonych słów, przedstawiony w poprzednim rozdziale. Wspo-
mniano tam, że pełne rozwiązanie można byłoby napisać w zaledwie kilku linijkach Perla. Przy-
kład znajduje się poniżej:
$/ = .\n ;
while ( ) {
next if !s/\b([a-z]+)((\s| [^ ]+ )+)(\1\b)/\e[7m$1\we[m$2\e[7m$4\e[m/ig;
s/^([^\e]*\n)+//mg; # usuwamy nieoznaczone wiersze
s/^/$ARGV: /mg; # rozpoczynamy wiersze od nazwy pliku
print;
}
Tak, to już cały program.
Zapewne nie jest on jeszcze całkowicie zrozumiały, chodzi tu tylko o ukazanie możliwości, których
nie posiada egrep i zwiększenie apetytu Czytelnika na prawdziwą siłę wyjrażeń regularnych — nie-
mal całe działanie powyższego programu opiera się na tjrzech takich wyrażeniach:
\b([a-z]+)((\s| [^ ]+ +)+)(\1\b)
^([^\e]*\n)+
^
Na pewno zrozumiałe jest ostatnie z nich, ^(cid:2). W pozostałych jednak występują elementy nie oma-
wiane w poprzednim rozdziale (choć o symbolu \b(cid:2) napisaliśmy krótko na stronie 39, wspomina-
jąc, że czasem reprezentuje on granicę słowa — tę samą rolę pełni on także tutaj). Wynika to z faktu,
że odmiana wyrażeń regularnych zastosowana w Perlu różni się od tej z egrepa. Różne są niektóre
sposoby zapisu, a poza tym Perl udostępnia o wiele bogatszy zestaw metaznaków. Przekonamy się o
tym na przykładach zamieszczonych w tym rozdziale.
Perl umożliwia o wiele bardziej zaawansowane użycie wyrażeń regularnych niż egrep. Dzięki
przykładom w Perlu poznamy dalsze sposoby wykorzystania wyrażeń regularnych i — co ważnie-
jsze — zobaczymy, jak zachowują się w innym kontekścije niż w przypadku programu egrep.
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strona 45
3.+o
6o+.;6+
/q6/19+62-
Przedstawiana tu odmiana wyrażeń regularnych jest podobna do opisanej w poprzednim rozdziale,
choć trochę się od niej różni.
Omawiane w tym rozdziale przykładowe problemy, takie jak weryfikacja danych wprowadzanych
przez użytkownika czy operacje na nagłówkach poczty elektronicznej, staną się okazją do dalszego
zagłębiania się w krainę wyrażeń regularnych. Przyjrzymy się pokrótce Perlowi i przeanalizujemy
niektóre procesy myślowe związane z budowaniem wyrażeń regularnych. Z tak wyznaczonej ścieżki
będziemy jednak co pewien czas zbaczać i omawiać inne ważne pojęcia. Jako język programowania,
Perl nie jest jakimś wyjątkowym zjawiskiem. Równie dobrze można by było wykorzystać dowolny
inny zaawansowany język (np. Tcl, Python, czy nawet elisp programu GNU Emacs) jednak Perl jest
tu najodpowiedniejszy dlatego, że spośród wymienionych języków w nim właśnie wyrażenia regu-
larne są najgłębiej zakorzenione; jest też chyba najszerzej dostępny. Perl posiada również wiele
użytecznych, zwięzłych konstrukcji do operowania na danych, dzięki którym sam wykonuje znaczną
część „ciężkiej roboty” i pozwala skoncentrować się na właściwych wyrażeniach regularnych. Aby
powyższe słowa brzmiały bardziej wiarygodnie, przypomnimy przykład z analizowaniem plików ze
strony 18. Wykorzystano tu właśnie Perla, a całe polecenie brzmiało następująco:
perl -0ne print $ARGV\n if s/ResetSize//ig != s/SetSize//iwg *
Być może nie jest ono jeszcze dla Czytelnika zrozumiałe, ale samą zwartością rozwiązania na
pewno robi wrażenie.
Trzeba tu jednak pamiętać o uniknięciu pułapek języka, miejmy bowiem na uwadze fakt, że roz-
dział ten koncentruje się na wyrażeniach regularnych. Przypomina to nieco słowa, które pewien
profesor informatyki skierował do studentów pierwszego roku: „Teraz będziemy poznawać zaga-
dnienia informatyczne, a do ich zademonstrowania posłużymy się Pascalem” (Pascal to tradycyjny
język programowania, pierwotnie przeznaczony do nauczjania).1
Ponieważ nie wymaga się tu od Czytelnika znajomości Perla, przed omówieniem przykładów za-
mieszczono wprowadzenie (pewnej podstawowej wiedzy o Perlu wymaga za to rozdział 7, prze-
dstawiający istotne szczegóły tego języka). Nawet osobom, które mają doświadczenie z różnymi
językami programowania, Perl może na pierwszy rzut oka wydać się odmienny — ma bardzo
uproszczoną i czasem dziwną składnię. Prezentowane przykłady nie są może „złe” pod względem
stylu programowania w tym języku, ale nie są też „doskonałe”. Dążąc do zrozumiałości przykładów
może nie wykorzystaliśmy wszystkiego, co Perl może zaoferować — programy są tu przedstawione
raczej w sposób ogólny, niemal jako „pseudokod”. Można natomiast tu znaleźć naprawdę ciekawe
zastosowanie wyrażeń regularnych.
/66(cid:8)8/;463;+./2/
Perl to język programowania o ogromnych możliwościach. Został stworzony przez Larry’ego
Walla w późnych latach osiemdziesiątych, a przy jego budowie czerpano pomysły z innych języ-
ków. Wiele sposobów przetwarzania tekstu i wyrażeń rjegularnych pochodzi z awka i seda, te nato-
miast znacznie się różnią od „tradycyjnych” języków, takich jak C czy Pascal. Perl jest dostępny
dla wielu systemów, w tym dla DOS-u, Windows, MacOS, OS/2, VMS i Uniksa. Jego możliwości
objawiają się szczególnie przy przetwarzaniu tekstu; jest też bardzo często wykorzystywany do
tworzenia skryptów CGI na potrzeby serwisów WWW (programy CGI służą do tworzenia i wy-
świetlania dynamicznych stron WWW). Informacje o tym, jak zdobyć kopię Perla dla swojego
1
Podziękowania za przykład należą się Williamowi F. aMatonowi oraz jego profesorowi.
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strona 46
46o+.+-
systemu zamieszczono w dodatku A. Omówienie w tej książce dotyczyć będzie Perla w wersji
5.003, ale prezentowane tu przykłady zostały napisane tak, że będą działały w wersji 4.036 lub
późniejszych.2
Spójrzmy na prosty przykład:
$celsjusz = 30;
$fahrenheit = ($celsjusz * 9 / 5) + 32; # obliczamy stopnie Fahrenheita
print $celsjusz C to $fahrenheit F.\n ; # drukujemy obie temperatury
Po wykonaniu programu otrzymamy taki wynik:
30 C to 86 F.
Proste zmienne, takie jak $fahrenheit czy $celsjusz, zawsze rozpoczynają się znakiem dola-
ra i mogą zawierać liczbę lub dowolną ilość tekstu (w tym przykładzie przypisano im tylko liczby).
Komentarze rozpoczynają się znakiem # i kończą wraz z końcem wiersza. Dla osób przyzwyczajo-
nych do tradycyjnych języków programowania, takich jak C czy Pascal, prawdopodobnie najbardziej
zaskakujące jest, iż zmienne mogą znajdować się wewnątrz łańcuchów objętych cudzysłowami.
W łańcuchu $celsjusz C to $fahrenheit F.\n pod obie zmienne podstawiane są ich
wartości. Tak uzyskany wiersz jest następnie wyświetlajny (\n reprezentuje znak nowego wiersza).
W Perlu można też używać instrukcji sterujących, podobjnie jak w innych popularnych językach:
$celsjusz = 20;
while ($celsjusz = 45)
{
$fahrenheit = ($celsjusz * 9 / 5) + 32; # obliczamy Fahrenheita
print $celsjusz C to $fahrenheit F.\n ;
$celsjusz = $celsjusz + 5;
}
Treść zawarta wewnątrz pętli while jest wykonywana dopóty, dopóki warunek (w tym przypadku
brzmiący: $celsjusz = 45) jest prawdą. Jeśli powyższy tekst umieścimy w pliku, np. o na-
zwie temperatury, będziemy mogli uruchomić taki program wprost z wiersjza poleceń:
perl -w temperatury
20 C to 68 F.
25 C to 77 F.
30 C to 86 F.
35 C to 95 F.
40 C to 104 F.
45 C to 113 F.
Opcja -w nie jest konieczna, nie ma też bezpośrednio nic wspólnego z wyrażeniami regularnymi.
Informuje po prostu Perla, aby dokładniej sprawdzał wykonywany program i ostrzegał użytkownika
za każdym razem, gdy znajdzie jakąś nieprawidłowość (np. niezainicjalizowane zmienne — zmie-
nne nie muszą być w Perlu wcześniej deklarowane). Opcję tę zastosowano tu tylko po to, aby
wpoić Czytelnikom nawyk jej używania.
2
Choć wszystkie przykłady w tym rozdziale dają się uruchomić we wcześniejszych wersjach Perla, autor bardzo
namawia do korzystania z wersji 5.002 lub późniejszej, bardzo natomiast odradza korzystanie z archaicznej wersji
4.036, chyba że naprawdę nie ma innego wyjścia.
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strojna 47
3.+o
6o+.;6+
/q6/19+62-
Wyrażenia regularne są w Perlu wykorzystywane na rozmaite sposoby. Najprostszy z nich polega
na sprawdzeniu, czy wyrażenie regularne może zostać dopasowane do tekstu przechowywanego
w zmiennej. Poniższy fragment programu sprawdza, czy w zmiennej $odpowiedz znajdują się
wyłącznie cyfry:
if ($odpowiedz =~ m/^[0-9]+$/) {
print tylko cyfry\n ;
} else {
print nie tylko cyfry\n ;
}
Składnia pierwszego wiersza może wydawać się nieco osobliwa. Wyrażenie regularne to ^[0-
9]+$(cid:2), natomiast otaczająca je konstrukcja m/…/ wskazuje Perlowi, co trzeba z tym wyrażeniem
zrobić. Litera m oznacza, że Perl ma podjąć próbę dopasowania wyrażenia regularnego do zmie-
nnej, natomiast ukośniki wyznaczają granice samego wyrażenia. Symbol =~ łączy konstrukcję
m/…/ z dopasowywanym łańcuchem znaków — w tym przypadku łańcuch ten jest zawarty w zmien-
nej $odpowiedz.
Nie należy mylić sekwencji =~ z = lub ==, ponieważ jest to coś zupełnie innego. Operator == te-
stuje, czy dwie liczby są takie same (do testowania identyczności łańcuchów służy, jak się wkrótce
przekonamy, operator eq). Operator = wykorzystywany jest do przypisywania wartości zmiennej,
np. $celsjusz = 20. Wreszcie zapis =~ służy do łączenia konstrukcji wyszukującej z prze-
szukiwanym łańcuchem znaków (w przykładzie konstrukcją wyszukującą jest m/^[0-9]+$/,
a przeszukiwanym łańcuchem — $odpowiedz). Być może wygodniej byłoby czytać zapis =~
jako „pasuje do” — wtedy zapis:
if ($odpowiedz =~ m/^[0-9]+$/) {
można by przeczytać jako:
„jeśli tekst w zmiennej $odpowiedz pasuje do wyrażenia regularnego ^[0-9]+$(cid:2), wtedy…”
Wynik całego wyrażenia $odpowiedz =~ m/^[0-9]+$/ ma wartość prawda, jeśli wyrażenie
^[0-9]+$(cid:2) pasuje do łańcucha $odpowiedz; w przeciwnym razie ma wartość fałsz. Instru-
kcja if korzysta potem z tej wartości, decydując na jej podjstawie, który komunikat wydrukować.
Zauważmy, że test o postaci $odpowiedz =~ m/[0-9]+/ (taki sam jak poprzednio, ale bez
daszka na początku i dolara na końcu) zwróciłby wartojść prawda, jeśli zmienna $odpowiedz za-
wierałaby przynajmniej jedną cyfrę w dowolnym miejscu. Symbole ^…$(cid:2) zapewniają, że zmienna
$odpowiedz musi zawierać wyłącznie cyfry.
Połączmy dwa ostatnie przykłady. Poprosimy użytkownika o wpisanie jakiejś wartości, przypiszemy
tę wartość zmiennej, a potem za pomocą wyrażenia regularnego sprawdzimy, czy jest liczbą. Jeśli
tak — program wyświetli odpowiednik w stopniach Fahrenheita. Jeśli nie, pojawi się ostrzeżenie.
print Wpisz temperaturę w stopniach Celsjusza:\n ;
$celsjusz = STDIN ; # wczytujemy jeden wiersz podany przez użytkownika
chop($celsjusz); # usuwamy znak koñca wiersza ze zmiennej $celsjusz
if ($celsjusz =~ m/^[0-9]+$/) {
$fahrenheit = ($celsjusz * 9 / 5) + 32; # obliczamy stopnie Fahrenheita
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strona 48
79;+2/8/789+433-;6+
/q6/19+62-
print $celsjusz C = $fahrenheit F\n ;
} else {
print Oczekiwano wprowadzenia liczby, zapis \ $celsjusz\ w jest
niezrozumiały.\n ;
}
Można zauważyć, że sposób „anulowania” znaków cudzysłowu w ostatniej instrukcji print jest
podobny do sposobu, w jaki eliminuje się specjalne znaczenie metaznaków w wyrażeniu regular-
nym. Więcej szczegółów na ten temat zamieszczono kilka stron dalej ((cid:1)54), w części Mała
dygresja — Firmament metaznaków.
Spróbujemy zapisać nasz program w pliku c2f i uruchomić go:
perl -w c2f
Wpisz temperaturę w stopniach Celsjusza:
22
22 C = 71.599999999999994316 F
Niestety, wygląda na to, że zwykła funkcja print nie radzi sobie najlepiej z liczbami zmienno-
przecinkowymi. Aby nie zagłębiać się tutaj we wszystkie detale Perla, zasugerujemy użycie w tym
miejscu funkcji printf (ang. print formatted) — wydruk będzie wyglądać wtedy lepiej (printf
przypomina funkcję printf z języka C oraz funkcje formatujące tekst z języków Pascal, Tcl,
elisp i Python):
printf .2f C = .2f F\n , $celsjusz, $fahrenheit;
Nie spowoduje to zmiany wartości zmiennych, a jedynie sposobu ich wyświetlania. Działanie pro-
gramu powinno teraz przebiegać następująco:
perl -w c2f
Wpisz temperaturê w stopniach Celsjusza:
22
22.00 C = 71.60 F
co oczywiście wygląda o wiele lepiej.
6o+.,
76/-;783-
Nasz przykład dobrze byłoby rozszerzyć tak, by można było podawać wartości ujemne i ułamkowe.
Część matematyczna programu nie wymaga zmian — liczby całkowite i zmiennoprzecinkowe Perl
traktuje tak samo. Trzeba jednak zmienić wyrażenie regularne tak, by nie powodowało wy-
świetlenia komunikatu o błędzie w przypadku podania liczby ułamkowej lub ujemnej. W tym celu
należy na początku dopisać wyrażenie -?(cid:2), co pozwoli rozpocząć treść zmiennej znakiem minusa.
Właściwie można nawet dodać ciąg [-+]?(cid:2), tak by na początku dopuszczalny był również plus.
Aby dopuścić możliwość wpisania części dziesiętnej, dopiszemy wyrażenie (\.[0-9]*)?(cid:2).
Sekwencja unikowa z kropką pasuje do dosłownego znaku kropki (w krajach anglojęzycznych,
a także w Perlu, część ułamkową oddziela się od całkowitej kropką, a nie, jak w Polsce, przecin-
kiem), a więc wyrażenie \.[0-9]*(cid:2) odpowiada kropce, po której znajduje się dowolna liczba
dowolnych cyfr. Ponieważ wyrażenie \.[0-9]*(cid:2) jest ujęte w znaki (…)?(cid:2), będzie ono opcjo-
nalne jako całość (jest to logicznie różne od \.?[0-9]*(cid:2) — tutaj cyfry zostałyby dopasowane
nawet wtedy, gdyby nie dopasowano kropki).
Cały wiersz kontrolujący poprawność wpisu wygląda więc jnastępująco:
if ($celsjusz =~ m/^[-+]?[0-9]+(\.[0-9]*)?$/) {
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strojna 49
3.+o
6o+.;6+
/q6/19+62-
Teraz już można wpisywać takie liczby jak 32, -3.723 czy +98.6. Wyrażenie to nie jest jednak
idealne: nie pozwala na wpisywanie liczb rozpoczynających się od kropki (np. .357). Oczywiście
użytkownik może zawsze podać na początku zero (czyli 0.357), nie jest to więc jakaś ogromna
wada. Problem ułamków ma jeszcze inne ciekawe aspekty, o których szczegółowo powiemy
w rozdziale 4. ((cid:1)135).
#989,3-2/9.+2/13.34+73;+2+
Rozbudujmy nasz przykład jeszcze bardziej i pozwólmy na wpisywanie wartości albo w stopniach
Celsjusza, albo Fahrenheita. Użytkownik będzie do wpisywanej liczby dodawał odpowiednio C
lub F. Aby nasze wyrażenie regularne na to pozwoliło, wystarczy dodać — po części dopasowują-
cej liczbę — zapis [CF](cid:2). Ale przecież musimy także zmienić resztę programu tak, by rozpozna-
wał, w jakiej skali wpisano temperaturę i na jaką najleży ją przeliczyć.
Perl, podobnie jak inne języki wykorzystujące wyrażenia regularne, posiada zestaw użytecznych
zmiennych pozwalających na odwoływanie się do tekstu dopasowanego wcześniej do wyrażeń
regularnych ujętych w nawiasy. W pierwszym rozdziale powiedzieliśmy, że niektóre wersje pro-
gramu egrep rozpoznają metasekwencje \1(cid:2), \2(cid:2), \3(cid:2) itd. umieszczone wewnątrz samego wy-
rażenia regularnego. Perl także obsługuje te metasekwencje, a oprócz tego pozwala odwoływać się
do fragmentów wyrażenia regularnego na zewnątrz niego, już po zakończeniu dopasowywania.
Takie odwołania realizowane są za pomocą zmiennych $1, $2, $3 itd. Wygląda to może trochę
dziwnie, ale to są zmienne, tyle że ich nazwy są liczbami. Perl nadaje im wartości za każdym ra-
zem, gdy dopasowanie wyrażenia regularnego się powiedzie. Metaznaku \1(cid:2) można użyć we-
wnątrz wyrażenia regularnego w celu odwołania do tekstu dopasowanego wcześniej podczas tej
samej próby dopasowywania. Natomiast zmiennej $1 należy użyć, by odwołać się do dopaso-
wanego tekstu w programie już po zakończeniu udanego dopasowania.
Aby zachować przejrzystość przykładu i ułatwić przyswojenie nowych wiadomości, usuniemy na
chwilę z naszego wyrażenia część związaną z ułamkami dziesiętnymi (powrócimy do nich wkró-
tce). Żeby poznać działanie zmiennej $1, porównajmy poniższe dwa wyrażenia:
$celsjusz =~ m/^[-+]?[0-9]+[CF]$/
$celsjusz =~ m/^([-+]?[0-9]+) ([CF])$/
Czy dodanie nawiasów okrągłych zmienia znaczenie wyrażenia? Aby uzyskać odpowiedź na to
pytanie, musimy sprawdzić, czy nawiasy te:
grupują elementy na potrzeby gwiazdki lub innego kwantyjfikatora;
ograniczają wyrażenia rozdzielone znakiem |(cid:2).
Odpowiedź na powyższe pytania brzmi „nie”, a więc obydwa wyrażenia pasują do tego samego
ciągu. Jednak nawiasy okrągłe obejmują dwa podwyrażenia — te „interesujące” z naszego punktu
widzenia. Jak pokazano na rysunku 2.1, zmienna $1 będzie zawierała wpisaną liczbę, zaś zmienna
$2 — albo literę C, albo F. Jeśli teraz spojrzymy na sieć działań przedstawioną na rysunku 2.2,
zobaczymy, że znając zawartość tych zmiennych możemy w prosty sposób pokierować działaniem
programu po dopasowaniu.
Zakładając, że pokazany dalej program nazwiemy konwersja, jego użycie wyglądałoby następująco:
perl -w konwersja
Wpisz temperaturę (np. 32F, 100C):
39F
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strona 50
79;+2/8/789+433-;6+
/q6/19+62-
792/
+;+746/-;89-/
792/
1368.+o+2+46316+932;/689
-/138/4/6+896
3.89 C = 39.00 F
perl -w konwersja
Wpisz temperaturę (np. 32F, 100C):
39C
39.00 C = 102.20 F
perl -w konwersja
Wpisz temperaturę (np. 32F, 100C):
ojejku
Oczekiwano wprowadzenia temperatury, zapis ojejku jest niezrozumiały.
print Wpisz temperaturę (np. 32F, 100C):\n ;
$lancuch = STDIN ; # wczytujemy jeden wiersz podany przez użytkownika
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strojna 51
3.+o
6o+.;6+
/q6/19+62-
chop($lancuch); # usuwamy znak końca wiersza ze zmiennej $celsjusz
if ($lancuch =~ m/^([-+]?[0-9]+)([CF])$/)
{
# jeżeli znajdziemy się w tym miejscu programu,
# to znaczy, że dopasowanie się powiodło
# $1 zawiera liczbę, a $2 literę C lub F
$liczba = $1; # zachowujemy wartości w nazwanych zmiennych,
$typ = $2; # co uprości czytanie pozostałej części programu
if ($typ eq C ) { # eq sprawdza, czy 2 łańcuchy są identyczne
# podano temperaturę w Celsjuszach, przeliczamy na F.
$celsjusz = $liczba;
$fahrenheit = ($celsjusz * 9 / 5) + 32;
} else {
# a więc jednak podano Fahrenheita -- przeliczamy na Ce.
$fahrenheit = $liczba;
$celsjusz = ($fahrenheit - 32) * 5 / 9;
}
# w tej chwili znamy już obie temperatury, więc
# wyświetlamy wynik
printf .2f C = .2f F\n , $celsjusz, $fahrenheit;
} else {
print Oczekiwano wprowadzenia temperatury, zapis \ $lancuch\w jest
niezrozumiały.\n ;
}
34+73;+2++2/13;+2/
Nasz program ma następującą strukturę logiczną:
if ( test logiczny ) {
… DŁUGIE PRZETWARZANIE jeżli zwrócono wynik prawda …
} else {
… tylko trochę przetwarzania, jeżli zwrócono wynik faelsz …
}
Każdy student programowania strukturalnego wie (lub powinien wiedzieć), że kiedy jedna gałąź
konstrukcji if jest krótka, a druga długa, to — o ile to tylko jest praktycznie wykonalne — lepiej
umieścić tę krótką na początku. Dzięki temu else jest bliżej if, co ułatwia przetwarzanie kodu.
Aby zrobić tak z naszym programem, musimy odwrócić sens testu. Krótsza część to ta, która mó-
wi „jeśli nie pasuje”, a więc test powinien zwracać wartość prawda wtedy, gdy dopasowanie się
nie powiedzie. Można to, zrobić zamieniając zapis =~ na !~, tak jak to pokazano poniżej:
$lancuch !~ m/^([-+]?[0-9]+([CF])$/
Wyrażenie regularne i badany łańcuch pozostają bez zmian. Jedyna różnica polega na tym, że wynik
całej kombinacji przyjmuje teraz wartość fałsz, jeśli wyrażenie regularne pasuje do łańcucha oraz
wartość prawda w przeciwnym przypadku. Jeśli nastąpi dopasowanie, zmiennym $1, $2 itd. zostaną
tak samo nadane wartości. Dlatego ta część naszego progrjamu wyglądałaby teraz następująco:
if ($lancuch !~ m/^([-+]?[0-9]+)([CF])$/) {
print Oczekiwano wprowadzenia temperatury, zapis \ $lancuch\ jestw
niezrozumiały.\n ;
} else {
# jeżeli znajdziemy się w tym miejscu programu,
# to znaczy, że dopasowanie się powiodło
# $1 zawiera liczbę, a $2 literę m C lub F
…
}
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strona 52
79;+2/8/789+433-;6+
/q6/19+62-
6/4+8+2/;6+
/q6/19+62-
W zaawansowanych językach programowania, takich jak Perl, wyrażenia regularne mogą w du-
żym stopniu przeplatać się z resztą programu. Aby przedstawić to na przykładzie, wprowadzimy
teraz do naszego programu trzy pożyteczne zmiany: umożliwimy wpisywanie liczb ułamkowych,
tak jak to robiliśmy wcześniej, zezwolimy na wpisywanie małych liter f i c oraz zezwolimy na
występowanie spacji pomiędzy liczbą a literą. Po takich zmianach użytkownik będzie mógł wpisać
np. 98.6f.
Jak wspomniano wcześniej, obsługę ułamków realizuje się poprzez dodanie wyrażenia (\.[0-
9]*)?(cid:2):
if ($lancuch =~ m/^([-+]?[0-9]+(\.[0-9]*)?)([CF])$/)
Zauważmy, że nowy fragment dodano wewnątrz pierwszej pary nawiasów okrągłych. Ponieważ za
pomocą tej pary nawiasów identyfikujemy liczbę do przeliczenia, musimy przechwycić ją wraz
z ułamkami. Chociaż dodatkowa para nawiasów okrągłych służy wyłącznie do grupowania elemen-
tów na potrzeby znaku zapytania, powoduje ona efekt uboczny polegający na przypisaniu do zmien-
nej znajdującej się wewnątrz nich wartości. Ponieważ nawias otwierający jest w tym przypadku
drugim nawiasem otwierającym od lewej strony, wartość przypisana zostaje do zmiennej $2. Do-
brze obrazuje to rysunek 2.3.
792/
+;+7+12/
.
32/
Widzimy, w jaki sposób nawiasy otwierające i zamykające są zagnieżdżone jedne w drugich. Do-
danie pary nawiasów przed wyrażeniem [CF](cid:2) nie powoduje bezpośrednio zmiany jego znacze-
nia. Jest jednak wpływ pośredni: teraz nawiasy otaczające to wyrażenie stanowią już trzecią parę
nawiasów, a to znaczy, że zmiennej $typ musimy przypisać wartość zmiennej $3, a nie $2.
Umożliwienie wpisywania spacji pomiędzy liczbą a literą nie jest aż takie skomplikowane. Wie-
my, że „czysta” spacja w wyrażeniu regularnym odpowiada dokładnie jednej spacji w dopasowy-
wanym tekście, a więc ciąg *(cid:2) pasuje do dowolnej liczby spacji (może też nie być jich wcale):
if ($lancuch =~ m/^([-+]?[0-9]+(\.[0-9]*)?) *([CF])$/)
Już w ten sposób zapewnia się pewną elastyczność dopasowania. Ponieważ jednak chcemy stwo-
rzyć coś, co ma być rzeczywiście użyteczne w praktyce, spróbujmy stworzyć wyrażenie regularne
pozwalające na wprowadzanie także innych białych znaków, na przykład często spotykanych zna-
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strojna 53
3.+o
6o+.;6+
/q6/19+62-
ków tabulacji. Oczywiście wyrażenie (cid:4)*(cid:2) uniemożliwi użycie zwykłych spacji, musimy więc
stworzyć klasę znaków zawierającą i znaki tabulacji, i spacje: [(cid:4)]*(cid:2). A teraz krótka kartkówka:
czym różni się to wyrażenie od (*|(cid:4)*)(cid:2)? L Odpowiedź znajduje się na stronie 56.
W tej książce spacje i znaki tabulacji łatwo odróżnić, zostały bowiem zaznaczone specjalnymi
symbolami oraz (cid:4). Niestety, na ekranie nie jest już tak łatwo. Jeśli widzimy zapis w rodzaju
[ ]*, możemy zgadywać, że pewnie jest to spacja i znak tabulacji, ale nie upewnimy się, dopóki
tego nie sprawdzimy. Perl ułatwia nam nieco życie, udostępniając metaznak \t(cid:2). Pasuje on po
prostu do znaku tabulacji, a jego jedyną zaletą w stosunku do „prawdziwego” znaku jest to, że le-
piej go widać (i dlatego będziemy z niego korzystali w wyrażeniach). Zatem zamieniamy zapis [
(cid:4)]*(cid:2) na [\t]*(cid:2)
A oto kilka innych wygodnych metaznaków: \n(cid:2) (newline — znak nowego wiersza), \f(cid:2) (form
feed — znak wysuwu strony) oraz \b(cid:2) (backspace — znak cofania). Ale chwileczkę — wcześniej
przypisaliśmy \b(cid:2) do granicy słowa. Cóż więc oznacza ten znak? Otóż oznjacza on i to, i to!
+o+.16/7+06+/28/8+2+(cid:24);
We wcześniejszych przykładach występowała sekwencja \n, jednak nie znajdowała się ona w wyraże-
niu regularnym, tylko w łańcuchu znaków. Łańcuchy Perla wykorzystują własne metaznaki, w ogóle
niezwiązane z metaznakami wyrażeń regularnych. Nowi programiści często mylą te dwa obszary.
Jak się jednak okazuje, niektóre metaznaki łańcuchów mają — dla ułatwienia — podobne znacze-
nia, jak te same metaznaki wyrażeń regularnych. Na przykład metaznak \t służy do wstawiania
znaku tabulacji do łańcucha, a podobny metaznak \t(cid:2) — odpowiada znakowi tabulacji wewnątrz
wyrażenia regularnego.
Takie podobieństwa są wygodne, trzeba jednak pamiętać, by ich nie mylić. Może wydaje się to
mało ważne dla prostego przykładu znaku \t, ale, jak zobaczymy przy okazji omawiania in-
nych języków i narzędzi, wiedza o tym, które metaznaki są wykorzystywane w jakiej sytuacji, jest
niezwykle istotna.
Konflikty pomiędzy metaznakami nie powinny być już niczym nowym. W rozdziale 1., przy okazji
omawiania programu egrep, wyrażenie regularne ujmowaliśmy w apostrofy. Cały wiersz poleceń
wpisywany jest po znaku zachęty, a interpreter rozpoznaje własne metaznaki. W pojęciu interpretera
metaznakiem jest np. spacja — oddziela ona polecenie od argumentów oraz poszczególne argumenty
między sobą. W wielu interpreterach apostrofy informują, że wewnątrz nich inne metaznaki mają
pozostać niezinterpretowane (w przypadku DOS-u takie znaczenie mają cudzysłowy).
Użycie apostrofów w przypadku interpretera pozwala na zastosowanie w wyrażeniu regularnym
znaków spacji. Bez apostrofów znaki te zostałyby przechwycone przez interpreter poleceń, a nie
przekazane do programu egrep. Wiele interpreterów rozpoznaje także inne metaznaki — $, *, ?
itd. — a przecież te z dużym prawdopodobieństwem mogąj pojawić się w wyrażeniu regularnym.
Cała ta opowieść o metaznakach interpretera i metaznakach w łańcuchach Perla nie ma nic wspólne-
go z samymi wyrażeniami regularnymi, jest natomiast silnie związana ze sposobem korzystania
z wyrażeń regularnych w praktyce. W wielu miejscach książki natkniemy się na złożone nie-
raz problemy, w których będzie trzeba wykorzystać możliwość „nakładania się” różnych pozio-
mów interpretacji metaznaków.
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strona 54
79;+2/8/789+433-;6+
/q6/19+62-
Wróćmy jednak do podwójnego znaczenia metaznaku \b(cid:2). Tym razem sprawa jak najbardziej
dotyczy wyrażeń regularnych. W Perlu sekwencja taka oznacza normalnie granicę słowa (ang.
boundary), ale wewnątrz klasy znaków służy do dopasowania znaku cofania (backspace). Wsta-
wianie granicy słowa wewnątrz klasy znaków nie miałoby sensu, a więc w takich miejscach Perl
może go interpretować inaczej. Zamieszczone w pierwszym rozdziale ostrzeżenie, że „pod-
język” klasy znaków jest inny od właściwego języka wyrażeń regularnych, jest na pewno aktualne
w przypadku Perla (i wszystkich innych odmian wyrażejń regularnych).
+o/2+9683;37
Przy omawianiu białych znaków poprzestaliśmy na wyrażeniu [\t]*(cid:2). Takie rozwiązanie dzia-
ła, ale mechanizm wyrażeń regularnych Perla pozwala zapisać je znacznie prościej. Podobnie jak
metaznak \t(cid:2) reprezentuje znak tabulacji, \s(cid:2) to skrótowy zapis oznaczający całą klasę znaków
zawierającą dowolny „biały znak”, czyli między innymi spację, znak tabulacji, nowego wiersza
i powrotu karetki (ang. carriage return). W naszym przykładzie znaki nowego wiersza i powrotu
karetki nie są i tak do niczego potrzebne, ale zapis \s*(cid:2) jest prostszy niż [\t]*(cid:2). Wkrótce
przyzwyczaimy się do widoku tego symbolu; jego znaczenie łatwo można zrozumieć nawet w zło-
żonych wyrażeniach regularnych.
Nasz test przybierze teraz postać:
$lancuch =~ m/^([-+]?[0-9]+(\.[0-9]*)?)\s*([CF])$/
Ostatnim udogodnieniem miało być umożliwienie wprowadzania zarówno wielkich, jak i małych
liter. Oczywiście, najprostszym sposobem byłoby dodanie małych liter do klasy znaków: [CFcf](cid:2),
jednak przedstawimy tu jeszcze inne rozwiązanie:
$lancuch =~ m/^([-+]?[0-9]+(\.[0-9]*)?)\s*([CF])$/i
Znak i jest tutaj modyfikatorem, a umieszczenie go po konstrukcji m/…/ jest dla Perla wskazówką,
że przy dopasowywaniu nie należy brać pod uwagę wielkości liter. Litera i nie jest częścią wy-
rażenia regularnego, lecz konstrukcji składniowej m/…/, która mówi Perlowi, co należy zrobić
z podanym wyrażeniem regularnym. Ponieważ nieco kłopotliwe byłoby ciągłe nazywanie wspo-
mnianego znaku „modyfikatorem i”, zazwyczaj wykorzystuje się zapis /i (choć w praktyce
dodatkowy ukośnik przed literą jest zwykle pomijany). W tym rozdziale poznamy jeszcze modyfi-
kator /g; na inne przyjdzie czas w dalszych częściach książkij.
Wypróbujmy teraz nasz program:
perl –w konwersja
Wpisz temperaturę (np. 32F, 100C):
32 f
10.0 C = 32.00 F
perl –w konwersja
Wpisz temperaturę (np. 32F, 100C):
50 c
10.00 C = 50.00 F
Coś się nie zgadza. Kiedy za drugim razem wpisano 50 Celsjusza, zostały one zinterpretowane ja-
ko 50 Fahrenheita. Dlaczego? Spójrzmy jeszcze raz na odpowijednią część programu:
if ($lancuch =~ m/^([-+]?[0-9]+(\.[0-9]*)?)\s*([CF])$/i)
{
…
$typ = $3; # zachowujemy wartości w nazwanych zmiennych,
C:\Andrzej\PDF\Wyrażenia regularne\02-11.doc — strojna 55
3.+o
6o+.;6+
/q6/19+62-
++/786(cid:8)
2-+43!.;6+
/2/ (cid:2)(cid:2)(cid:2)(cid:2)(cid:3)(cid:2)(cid:2)(cid:2)(cid:2)+ (cid:6)(cid:3)(cid:2)(cid:2)(cid:2)(cid:2)(cid:3)(cid:8)(cid:2)(cid:2)(cid:2)(cid:2)
L Odpowiedź na pytanie ze strony 54
Wyrażenie (*|(cid:4)*)(cid:2) odpowiada albo *(cid:2) albo (cid:4)*(cid:2), czyli pasuje do kilku spacji (lub
żadnej), albo kilku znaków tabulacji (lub żadnego). Nie umożliwia ono jednak dopasowa-
nia mieszaniny spacji i znaków tabulacji.
[(cid:4)]*(cid:2) pasuje do wyrażenia [(cid:4)](cid:2) powtórzonego dowolną liczbę razy. W łańcuchu
„(cid:4)” takie wyrażenie dopasowywane jest trzy razy, najpierw do znaku tabulacji, a po-
tem dwóch spacji.
[(cid:4)]*(cid:2) to logicznie to samo co (|(cid:4))*(cid:2), jednak użycie klasy znaków jest często
o
Pobierz darmowy fragment (pdf)