Hej!
Jak ten czas szybko leci... no wiec z tygodniowym opoznieniem i 6 serwerow dalej... lecimy z nastepna czescia kursu
Dzisiaj omowimy wyrazenia regularne - cos co jest jednym z najwiekszych skarbow w Perlu. Inne jezyki sa w tej kwestii dosc ubogie, od jakiegos czasu dopiero jest biblioteka libpcre, pcre to Perl Compatibile Regular Expressions (http://www.pcre.org/ hihi)... wiec widac skad takie cos sie wywodzi i gdzie zostalo to uzyte po raz pierwszy.
Przy okazji kursu Javy zaczalem szukac czy do Javy sa regexy (tak potocznie sie je nazywa od 'regular expressions') no i w koncu sa... dluuugo nie bylo ale juz sa jako czesc pakietu java.util.* - niestety sa bardzo podstawowe (choc mozna oczywiscie korzystac z innych klas dostarczonych przez innych ludzi). PHP ma regexy (preg_match, preg_replace, itd) - roznia sie nieco skladnia polecenia ale generalnie beda podobne... Np egrep uzywa praktycznie identycznej skladni.
Znaki uzywane w wyrazeniach regularnych
Kod:
^ - oznacza poczatek linii/wiersza/zmiennej - ogolnie poczatek tekstu
$ - j.w. tyle ze koniec
. - dowolny znak (pojedyncza kropka)
\w - tzw 'word' czyli zestaw A-Z, a-z, 0-9 oraz podkreslenie
\W - non-word - przeciwienstwo tego co wyzej
\s - znak bialy czyli spacja lub tabulacja
\S - znak nie-bialy
\d - cyfra (digit)
\D - nie-cyfra
itd... na razie sotaniemy przy tych. Temat wyrazen regularnych jest baaardzo szeroki - na tyle szeroki, ze sa do niego osobne ksiazki w ogole, wiec nie bedziemy za daleko tutaj sie zaglebiac.
Zapis wyrazenia regularnego
Na razie skupimy sie tylko na samym wyrazeniu, pozniej polaczymy je z kodem i zobaczymy jak dziala - tutaj zaczyna sie ogrom magii perla zwiazanej z analiza plikow tekstowych miedzy innymi. Wyrazenia bede zapisywal pomiedzy lamaniami / - tak jak to bedzie pozniej w kodzie - tak prosciej sie czyta.
Kod:
TEKST: 3 maja 2008 13:57:00 CET
Wyrazenie: /^\d \w\w\w\w \d\d\d\d \d\d:\d\d:\d\d \w\w\w$/;
Generalnie kaszana - niewygodne, nie skaluje sie itd... co by bylo gdyby byla data "01 kwietnia 2008" albo wiecej spacji miedzy elementami? Tego juz wyrazenie regularne nie zlapie... w takim razie trzeba jakos opisac ilosc znakow, dlugosc pol... a moze po prostu napisac ze, ma byc kilka znakow?
Wiecej znakow danego typu w wyrazeniu...
Regexy sa bardzo elastyczne... napiszmy np:
Kod:
\d - jedna cyfra
\d{1} - dokladnie jedna cyfra - jak wyzej
\d+ - jedna lub wiecej cyfr
\d{1,} - to samo
\d* - zero lub wiecej cyfr
\d{0,} - to samo
\d{,3} - od 0 a 3 cyfry
\d{2,5} - minimum 2 max 5 syfr
Oczywiscie ten sam zapis mozna uzywac w przypadku innych dowolnych grup znakow opisanych jak przyklady wyzej lub doslownie jako grup okreslonych przez uzytkownika (to tez jest mozliwe)
Kod:
/^\d{1,2}\s+\w+\s+\d{4}\s+\d{2}:\d{2}:\d{2}/
W tym wrazeniu dzien zapisalismy jako 1 lub 2 cyfry na poczatku tekstu, dalej 1+ znakow bialych (spacja, tabulacja), ciag word (tu nazwa miesiaca), dokladnie 4 cyfry (rok) i 3 dwucyfrowe czesci oznaczajace czas, nie interesuje nas dopasowanie nazwy strefy czasowej.
Teraz lekko modyfikujemy to co mamy - interesuje nas wylapanie tylko i wylacznie czasu - bez tego co jest po bokach.
zauwazcie ze nie ma juz ^ na poczatku linii ani $ na koncu, poniewaz tekst ktory dopasowujemy jest w srodku i nie siega do koncow. Bardzmy teraz jeszcze bardziej leniwi hihi
Wlasnie skrocilismy pierwsze dwa bloki i kazalismy je powtorzyc 2 razy oraz dodalismy ostatni, po ktorym nie ma juz dwukropka. No to jeszcze inaczej
Wlasnie dopasowalismy czas i strefe czasowa czyli znaki inne niz biale, znak bialy (1 lub wiecej) i word oraz koniec stringa.
Dopasowania "zachlanne" oraz tzw referencje wsteczne
W ostatnich 2 przykladach pojawilo sie cos nowego - nawiasy! Maja one specjalne znaczenie, ktore moze byc rozne interpretowane zaleznie od kontekstu w jakim zostaly uzyte...
Generalnie nawiasow uzywamy do grupowania wyrazen - tak jak 2 przyklad wyzej. Ostatni przyklad powyzej uzywa jednak nawiasow do tzw referencji wstecznych (jesli w ogole mozna to tak przetlumaczyc na polski).
Wstawmy ostatniego regexa do kodu (z lekka modyfikacja) i zobaczmy co sie stanie - przyklad...
Kod:
#!/usr/bin/perl
use strict;
my $tekst = '3 maja 2008 14:47:00 BST";
$tekst =~ m/(\S+)\s+(\w+)$/;
print "Godzina to $1 w strefie $2\n";
Ten przyklad zawiera 3 nowe rzeczy - po pierwsze operator =~, po drugie w regexie sa nawiasy ktore maja przechwycic wartosci zmiennych aby mozna je pozniej wyswietlic (to jest wlasnie 'backreference' ale nazywajmy je wynikiem dopasowania), po trzecie wykonalismy dopasowanie ktore nie jest zachlanne - to omowimy na koniec i pokazemy co to jest dopasownaie zachlanne i jak latwo mozna sie na nim 'przejechac' - co w sumie sam zrobilem piszac ta czesc hihi...
C.D.N.
EDIT - prosilem, ze jak pisze "C.D.N" to prosze nie wstawiac jeszcze swoich odpowiedzi bo bedzie ciag dalszy tej czesci...