Narzędzia informatyczne w językoznawstwie
Perl - Wyrażenia regularne
Marcin Junczys-Dowmunt junczys@amu.edu.pl
Zakład Logiki Stosowanej http://www.logic.amu.edu.pl
16. styczeń 2008
Marcin Junczys-Dowmunt Narzędzia informatyczne w językoznawstwie 1/20
Wyrażenia regularne w Perlu
I Na ostatnich zajęciach zapoznaliśmy się z Wyrażeniami Regularnymi na sucho, dziś omówimy ich integrację w Perlu.
I Na wykładzie dotyczącym haszów poznaliśmy jedno z najpotężniejszych narzędzi Perla, drugim (lub pierwszym?) najważniejszym mechanizmem tego języka są właśnie RE (Regular Expressions, będziemy stosowali taki skrót)
I RE same w sobie nie są może szczególnie potężne, ale w połączeniu z językiem programowania, można wykorzystać je do wielu różnych zadań
I Wyrażenia regularne w Perlu ustanowiły pewien standard:
PCRE (Perl Compatible Regular Expressions)
I Większość szanujących się programów korzysta właśnie z tego standardu, inne standardy RE są raczej egzotyczne
Marcin Junczys-Dowmunt Narzędzia informatyczne w językoznawstwie 2/20
Pierwsze przykłady
1 p r i n t " D o p a s o w a n o \ n " if(" H e l l o W o r l d " =~ / W o r l d /);
p r i n t " Nie d o p a s o w a n o \ n " if(" H e l l o W o r l d " !~ / W o r l d /);
5 $ r e g = ’ W o r l d ’;
p r i n t " D o p a s o w a n o \ n " if(" H e l l o W o r l d " =~ / $ r e g /);
I RE otaczamy w Perlu operatorami /.../
I Porównując zmienną lub łańcuch z RE korzystamy z
operatorów =~ (dopasowanie pozytywne) lub !~ (dopasowanie negatywne)
I Wewnątrz operatorów /.../ działa interpolacja zmiennych, trzeba pamiętać o związku cudzysłowu podwójnego ze znakiem \
Przykład bardziej sensowny – perlowy minigrep.pl
1 my $ r e g e x p = s h i f t @ A R G V ; w h i l e( < >) {
p r i n t if(/ $ r e g e x p /);
}
I Unixowy Grep to program, który wyświetla wiersze (i inne informacje) z pliku lub z plików tekstowych, które pasują do podanego wzorca, np.
grep "\b[Aa]dam\b" plik1.txt
I Nasz prosty program perlowy minigrep.pl działa podobnie, np. perl minigrep.pl "\b[Aa]dam\b" plik1.txt Z tym, że nie informuje o nazwie pliku lub numerze wiersza (patrz zadanie domowe)
I Jak widać użycie samego operatora /.../ powoduje porównywanie ze zmienną standardową
Sortowanie mieszane raz jeszcze
1 my @ m i e s z a n e = (4 ," A n t e k ",13 ,9 ," Z e n o n ",2 ,10 ," M i r e k ");
p r i n t j o i n(" , ", s o r t {
i s _ n u m ( $a ) && i s _ n u m ( $b ) ? $a <= > $b : $a cmp $b ; } @ m i e s z a n e )." \ n ";
5
sub i s _ n u m {
my $ t e s t = s h i f t;
r e t u r n $ t e s t =~ / ^ [ + - ] ? \ d + ( \ . \ d + ) ? ( [ eE ][+ -]?\ d +)? $ /;
}
I Nie potrafiliśmy sortować alfabetycznie z liczbami
poprzedzającymi łańcuchy znakowe w porządku rosnącym
I Teraz potrafimy
I Funkcja is num sprawdza, czy dany łańcuch znakowy ma postać liczby
Marcin Junczys-Dowmunt Narzędzia informatyczne w językoznawstwie 5/20
Grupowania i odwołania do grup z poza RE
1 my $ r e c o r d = " Jan K o w a l s k i , 2 0 . 1 2 . 1 9 8 2 ";
$ r e c o r d =~ / ^ ( \ w +)\s(\ w +) ,\s([\ w . ] + ) $ /;
p r i n t " $2 , $1 u r o d z i l ( a ) sie d n i a $3 \ n ";
I Zmienne specjalne $1 do $9 odwołują się odpowiednio do grup \1 do \9, jeśli takie grupy nie zostały dopasowane to zmienne zawierają undef
I Wewnątrz RE korzystamy z odwołań typu \1, w programach ze zmiennych typu $1
I Dopasowanie w użyte w kontekście listowym powoduje przypisanie kolejnych grup do kolejnych elementów listy.
1 my $ r e c o r d = " Jan K o w a l s k i , 2 0 . 1 2 . 1 9 8 2 ";
my @gr = $ r e c o r d =~ / ^ ( \ w +)\s(\ w +) ,\s([\ w . ] + ) $ /;
p r i n t " $gr [1] , $gr [0] u r o d z i l ( a ) sie d n i a $gr [ 2 ] \ n ";
Marcin Junczys-Dowmunt Narzędzia informatyczne w językoznawstwie 6/20
Nawiasy niegrupujące
1 my $ n u m b e r = " n a s z a l i c z b a : -3.1105 e - 0 1 0 ";
$ n u m b e r =~ / ( [ + - ] ? \ d + ( ? : \ . \ d + ) ? ( ? : [ eE ] ( [ + - ] ? \ d + ) ) ? ) / ; p r i n t " L i c z b a $1 ma w y k ł a d n i k $2 \ n ";
I Standardowo każda para nawiasów generuje nową grupę (grupy numerujemy według nawiasów otwierających, niezależnie od głębokości zagnieżdżeń)
I Gdy korzystamy z kwantyfikatorów może to być działaniem niepożądanym
I Wtedy korzystamy z nawiasów niegrupujących (?:...)
Grupy nazwane
1 my $ r e c o r d = " Jan K o w a l s k i , J o a n n a N o w a k ";
$ r e c o r d =~ /^((? < imie >\ w +) (? < n a z w i s k o >\ w +)( , ) ? ) + $ /;
p r i n t " $ +{ n a z w i s k o } , $ +{ i m i e }\ n ";
I 18. grudnia 2007 pojawił się nowy Perl o numerze 5.10.0
I Od tej wersji działają tzw. grupy nazwane
I Grupę nazwaną tworzymy za pomocą konstrukcji (?<nazwa>...) lub (?’nazwa’...)
I Wewnątrz RE odwołujemy się do nich przez \gnazwa
I W programie odwołujemy się do nich przez specjalny hasz %+, np. $+{nazwa};
I Nazwy mogą się powtarzać, ale możemy się odwołać tylko do ostatniego dopasowania
Funkcja split - dzielenie rekordów i nie tylko
1 my $ r e c = " K o w a l s k i Jan 20 -12 -1984\ n ";
my ( $nazw , $imie , @ d a t a ) = s p l i t(/\s+|\ -/ , $ r e c );
p r i n t " $ i m i e $ n a z w u r o d z i l sie w r o k u $ d a t a [ 2 ] \ n ";
I Funkcja split jest jedną z bardziej przydatnych funkcji w Perlu, łącząca w sobie funkcjonalność RE i list
(przeciwieństwo funkcji join)
I Dzieli dany łańcuch znakowy na pola według podanego RE
I Jeśli podane RE nie zawiera nawisów, to części dopasowane nie znajdą się w liście wynikowej
I Jeśli RE zawiera nawiasy grupujące, to dopasowane grupy znajdują się w listach pomiędzy polami
1 my $ r e c = " K o w a l s k i Jan 20 -12 -1984\ n ";
my ( $nazw , $imie , @ d a t a ) = s p l i t(/\s+|(\ -)/ , $ r e c );
p r i n t j o i n(" : ", @ d a t a )." \ n ";
Marcin Junczys-Dowmunt Narzędzia informatyczne w językoznawstwie 9/20
Program tworzący listę frekwencynją raz jeszcze
1 my % f r e q ; w h i l e( < >) {
my @ t o k e n s = s p l i t( / [ \s. ,;?!:\ -()]+/ , $_ );
f o r e a c h my $ t o k e n ( @ t o k e n s ) {
5 $ f r e q { $ t o k e n } + + ; }
}
f o r e a c h my $ t o k e n (s o r t k e y s % f r e q ) { p r i n t " $ t o k e n $ f r e q { $ t o k e n }\ n ";
10 }
I W końcu znamy wszystkie narzędzia potrzebne do napisania programu zliczającego liczbę wystąpień wyrazów w tekście
I Korzystamy tutaj prawie ze wszystkich mechanizmów poznanych na wcześniejszych wykładach
I W jakim porządku jest wyświetlana lista frekwencyjna? Jaki porządek byłby bardziej przydatny?
Marcin Junczys-Dowmunt Narzędzia informatyczne w językoznawstwie 10/20
Flagi
1 $ z m i e n n e =~ / w z o r z e c / m s i g x
I Zachowywanie domyślne RE możemy modyfikować za pomocą tzw. flag
I Flagi mają postać pojedynczych liter umieszczanych bezpośrednio za operatorami RE /.../
I Flagi można ze sobą łączyć, przy czym niektóre kombinacje są szczególnie pożyteczne
Flaga i – (case) insensitive
1 my $ t e k s t = " d Z i W n A p I s O w N i A "
if( $ t e k s t =~ / p i s o w n i a / i ) {
p r i n t " D o p a s o w a n i e sie p o w i o d l o \ n ";
5 }
I Flaga i włącza tryb dopasowywania bez rozróżniania wielkości liter
I Flagę i należy stosować oszczędnie, ponieważ spowalnia proces dopasowywania RE
I Jeśli istnieje taka możliwość, to lepiej korzystać np. z odpowiednich klas znaków (np. gdy dopuszczalne są duże i małe litery na początku wyrazu)
Flaga g – global
1 my $ t e k s t = " The M e s s e n g e r s p a c e c r a f t d a s h e d p a s t M e r c u r y t o d a y ";
my @ t o k e n s = $ t e k s t =~ / ( [ \ w \ -]+)/ g ;
5 p r i n t " $_ \ n " f o r e a c h( @ t o k e n s );
I Domyślnie RE dopasują pierwsze możliwe wystąpienie szukanego wzorca i tylko pierwsze wystąpienie
I Flaga g powoduje, że dopasowane zostaną wszystkie pasujące wystąpienia wzorca
I Gdy jedno wystąpienie zostanie dopasowane, następne wystąpienie zostanie dopasowane dopiero za końcem poprzedniego dopasowania
I Jeśli w takim RE wykorzystamy nawiasy grupujące, najłatwiej odwołać się do grup poprzez tablicę
Marcin Junczys-Dowmunt Narzędzia informatyczne w językoznawstwie 13/20
Zastępowanie
1 $_ = " g r e e n s c a l y d i n o s a u r ";
s/(\ w +) (\ w +)/ $2 , $1 /; # scaly , g r e e n d i n o s a u r
s/^/ huge , /; # huge , scaly , g r e e n d i n o s a u r s/ ,.* een //; # h u g e d i n o s a u r
5 s/ g r e e n / red /; # h u g e d i n o s a u r
s/\ w + $ /( $ ‘!) $ &/; # h u g e ( h u g e !) d i n o s a u r s/\s+ ( ! \ W +)/ $1 /; # h u g e ( h u g e !) d i n o s a u r s/ h u g e / g i g a n t i c /; # g i g a n t i c ( h u g e !) d i n o s a u r
I Operator zastępowania s/.../.../ składa się dwóch części:
I W pierwszym polu znajduje się dowolne wyrażenie regularne
I W drugim polu znajduje się dowolny łańcuch znakowy (działający jak podwójnym cudzysłowu), a nie wyrażenie regularne
I Korzystamy ze zmiennych typu $1 a nie z odwołań typu \1
Marcin Junczys-Dowmunt Narzędzia informatyczne w językoznawstwie 14/20
Zastępowanie globalne oraz ewaluacja
1 $ t e k s t =~ s/ ( [ + - ] ? \ d + ( ? : \ . \ d + ) ? ) /log( $1 )/ eg ;
I Większość flag działa również w połączeniu z operatorem zastępowania
I Flaga g spowoduje zastąpienie wszystkich dopasowań w łańcuchu, nie tylko pierwszego
I Flaga e pozwala na wpisywanie kodu Perla do drugiego pola zastępowania.
I Tak naprawdę flaga e otacza drugie pole funkcją eval(), która wykonuje kod Perla zapisany w łańcuchu znakowym
Transliteracja
1 my $ n o r m a l i z a c j a = " m i ł o ś n i k żab ";
$ n o r m a l i z a c j a =~ tr/ ą ć ę ł ń ó ś ż ź / a c e l n o s z z /;
p r i n t $ n o r m a l i z a c j a ." \ n ";
I Transliteracja z operatorem tr/.../.../ często pojawia się w rozdziałach dotyczących RE, jednak tak naprawdę nie działa jak RE
I Pola operatora zawierają klasy znaków
I Każdy znak z pierwszego pola jest zastępowany znakiem na tej samej pozycji w klasie znaków z drugiego pola
I Gdy drugie pole zawiera mniej znaków niż pierwsze, to ostatni znak z drugiego pola dopełnia różnicę
Zachowanie kropki a flagi s i m
I Zachowanie standardowe. ’.’ dopasuje wszystkie znaki oprócz
”\n” . ^ dopasuje tylko początek łańcucha, a $ tylko koniec łańcuchy lub przed ”\n” na końcu łańcucha
I Flaga s: Traktuje łańcuch znakowy jak jedną długą linię. ’.’
dopasuje wszystkie znaki, łącznie z ”\n” . ^ dopasuje tylko początek łańcucha, a $ tylko koniec łańcuchy lub przed ”\n”
na końcu łańcucha
I Flaga m: Traktuje łańcuch znakowy jak zbiór wierszy. ’.’
dopasuje wszystkie znaki oprócz ”\n” . ^ i $ mogą dopasować początek i koniec każdego z wierszy.
I Flagi s i m: Traktuje łańcuch znakowy jak jedną długą linię, ale wykrywa obecność wielu wierszy. ’.’ dopasuje wszystkie znaki, łącznie z ”\n” . ^ i $ mogą dopasować początek i koniec każdego z wierszy.
Marcin Junczys-Dowmunt Narzędzia informatyczne w językoznawstwie 17/20
Flaga o – Kompilacja wzorców
1 my @ m i e s i a c e = qw( s t y c z n i a l u t e g o m a r c a . . . ) ; my $ p a t = j o i n(" | ", @ m i e s i a c e );
if(" 16. s t y c z n i a 2 0 0 8 " =~ /\ d \ d \. $ p a t \ d { 4 } / o ) {
5 p r i n t " D o p a s o w a n o \ n "; }
I Flaga o kompiluje nasze RE, tzn. że RE jest optymalizowane i staje się niezmienne (!)
I Optymalizację warto stosować, gdy wewnątrz RE odbywa się interpolacja zmiennych
I Proces dopasowywania przyspieszy wtedy znacznie
I Uwaga: Międzyczasowe zmiany zmiennej interpolowanej nie zmienią wzorca, będzie on miał postać, którą miał przy pierwszej kompilacji
Marcin Junczys-Dowmunt Narzędzia informatyczne w językoznawstwie 18/20
Flaga x – extended RE
1 my $ n u m b e r = " n a s z a l i c z b a : -3.1105 e - 0 1 0 ";
$ n u m b e r =~ / (
[+ -]? # o p c j o n a l n y z n a k
5 \ d + # c z ę ś ć c a ł k o w i t a m a n t y s y
( ? : \ . \ d +)? # o p j c o n a l n a c z ę ś ć u ł a m k o w a m a n t y s y (?:
[ eE ]
([+ -]?\ d +) # w y k ł a d n i k z o p c j o n a l n y m z n a k i e m
10 )? # w y k ł a d n i k też j e s t o p c j o n a l n y )
/ x ;
p r i n t " L i c z b a $1 ma w y k ł a d n i k $2 \ n ";
I Flaga x pozwala na bardziej czytelny zapis RE
I Białe znaki oraz komentarze są ignorowane
Jeśli chcemy dopasować spacje lub # korzystamy z \ oraz \#
Podsumowanie
I Poznaliśmy kilka podstawowych własności Wyrażeń Regularnych używanych w Perlu
I Jest jeszcze wiele własności, flag, znaków specjalnych, których jeszcze nie umówiliśmy: np. tzw. Look-Ahead
I Zachęcam bardzo do przeczytania innych źródeł, np. oficjalnej dokumentacji do Wyrażeń Regularnych w Perlu. Linki
znajdują się na stronie przedmiotu