index-1.html 100664 767 767 3776 6444314757 12253 0 ustar cassel cassel
Dokument ten to krótkie zapoznanie się z Perlem, zawiera on podstawowe
zagadnienia z tej dziedziny i może być dobrym punktem startowym dla osób
rozpoczynających swoją przygodę z tym językiem. W celu uzyskania lepszej
czytelności tekstu skupiłem się na przedstawieniu większości zagadnień na
przykładach. Informacje tutaj zawarte pochodzą z dokumentacji do języka w
wersji 5.003, początkowo pisząc go wzorowałem się na tutorialu opracowanym
przez
Nika Silvera
w
School of Computer Studies
(w porozumieniu z autorem).
Wersja z dnia 19.06.97 zawierała sporo usterek. Zostały one już poprawione. Tam gdzie zachodziła taka potrzeba tematy nieco uzupełniłem. Od teraz całość jest dostępna w postaci SGML. Dziękuję wielu osobom za kontakt i przydatne opinie i sugestie.
Dokument ten można rozprowadzać, lecz jedynie w niezmienionej formie (poza konwersją z sgml do innych formatów) i o ile nie pobierane są jakakolwiek opłaty z jego tytułu.
Perl to z założenia praktyczny, interpretowany język, przeznaczony przede
wszystkim do wykonywania różnych zadań systemowych m.in. przeszukiwania
plików tekstowych, pobierania z nich informacji i generowania komunikatów na
ich podstawie, świetnie nadaje się do pisania skryptów CGI. Posiada on wiele
cech języka C, jak również sed, awk i shella. Programujący w owych językach
nie powinni mieć większych probelmów z opanowaniem Perla. Kompilatory tego
języka są dostępne dla wielu systemów operacyjnych, większość skryptów jest
przenośna.
Archiwum CPAN
zawiera wiele interesujących materiałów
poświęconych Perlowi (kompilatory, skrypty, biblioteki).
Pierwsza linijka kodu w języku Perl ma specjalne znaczenie i powinna wyglądać następująco (aczkolwiek nie jest ona niezbędna do działania programu):
#!/usr/bin/perl
Ścieżka "/usr/bin/perl" zależy od konkretnego systemu i należy ją
odpowiednio zmodyfikować tak aby wskazywała ona interpreter. Podobnie jak w
zwykłych skryptach shella tak i w Perlu linie rozpoczynające się od znaku
"#" są ignorowane przez kompilator i pozwalają na umieszczanie własnych
komentarzy.
Oto najprostszy program w Perlu wypisujący na ekranie tekst:
#!/usr/bin/perl
print 'Hello World.'; # ten tekst zostanie wypisany na ekranie
Aby uruchomić taki program należy zapisać go w zwykłym pliku tekstowym. Możemy użyć do tego celu jakiegokolwiek edytora. Następnie nadajemy plikowi odpowiedni atrybut wykonywalności poleceniem "chmod u+x nazwa_pliku". Uruchamiamy program wywołując go z lini komend:
nazwa_programu # jeśli znajduje się on w katalogu na ścieżce
./nazwaprogramu # jeśli nie znajduje się w katalogu na ścieżce, a
# jest w katalogu bierzącym
perl nazwa_programu # podając go jako parametr dla interpretera (w tym
# przypadku atrybut wykonywalności pliku nie ma
# znaczenia)
Pomocną i stosunkowo nową w języku opcją interpretera jest "-w".
Powoduje ona wypisanie komunikatów dotyczących aktualnie wykonywanego
programu. Często dzięki niej możemy odnaleźć usterki niezauważone w procesie
kompilacji, a mimo to istotne dla działania programu.
W Perlu korzystanie ze zmiennych zostało maksymalnie uproszczone, nie trzeba ich tu w żaden specjalny sposób deklarować. Do wszelkich zmiennych skalarnych odwołujemy się umieszczając przed ich nazwą znak dolara. Przypisanie zmiennej "$a" wartości liczbowej "123" będzie miało postać:
$a = 123;
Aby przypisać zmiennej wartość łańcuchową "bleble" napiszemy pamiętając o
apostrofach:
$a = 'bleble';
Wypisywaliśmy już zwykły tekst, teraz dowiemy się jak to zrobić ze
zmiennymi. Duże znaczenie mają użyte apostrofy.
$a = 'jeden';
$b = 'dwa';
$c = 'trzy';
print $a.' - '.$b.' - '.$c; # wypisze "jeden - dwa - trzy"
print '$a - $b - $c'; # wypisze "$a - $b - $c"
print "$a - $b - $c"; # wypisze "jeden - dwa - trzy"
Tekst zawarty w pojedyńczym apostrofie jest traktowany jak zwykły ciąg
znaków. Tekst zawarty w podwójnym apostrofie może zawierać nazwy zmiennych,
które zostaną podmienione na ich wartości, jak również specjalne znaki np.
"\t" (tabulator), "\n" (nowa linia). Kompilator rozróżnia wielkie i małe
litery ("$A" to nie to samo co "$a"). Nazwy zmiennych dobierane są dowolnie,
mogą nimi być kobinacje liter i cyfr o nieograniczonej długości (poza
kilkoma wyjątkami, np. "$_", ich dokładniejszy opis pojawi się później).
Szerokie zastosowanie w programowaniu znajdują z pewnością tablice zmiennych (ang. array). Aby stworzyć tablicę i zapisać w niej wartości piszemy:
@imiona = ("kazik", "tomek", "marek");
Z tak przygotowanej tablicy możemy pobierać poszczególne elementy jak i je
zapisywać. Należy pamiętać, że elementy tablicy są numerowane począwszy od
zera:
$imiona[0] # tak przedstawiany jest pierwszy element tablicy
$imiona[1] = 'zyzio'; # tak zapisujemy do drugiego elementu tablicy
Ponieważ każdy element tablicy to zwykła zmienna skalarna, dlatego odwołując
się do niej używamy znaku dolara, a nie małpki. Tak dodajemy do tablicy nowe
elementy:
push(@imiona, "kasia"); # dodanie kolejnego - czwartego
# elementu do tablicy @imiona
push(@imiona, "kasia", "małgosia") # dodanie dwóch elementów na raz
@damy = ("kasia", "małgosia");
push(@imiona, @damy); # dodanie dwóch tablic do siebie
Tak można usunąć ostatni element tablicy i jednocześnie go zwrócić:
$a = pop(@imiona); # $a będzie zawierać wartość ostatniego,
# usuniętego elementu tablicy @imiona
Możliwe jest przyporządkowywanie zmiennym skalarnym tablic. Należy jednak
znowu zwrócić uwagę na użycie apostrofów:
$a = @imiona; # zmienna $a będzie zawierać liczbę elementów tablicy
$a = "@imiona"; # zmienna $a będzie łańcuchem składającym się z
# kolejnych elementów tablicy @imiona odzielonych spacjami
Numer ostatniego elementu tablicy otrzymujemy dzięki zastosowaniu zapisu:
$#imiona
Pozostała jeszcze kwestia wypisywania zawartości tablic:
print @imiona; # wypisuje elementy tablicy jednym ciągiem
print "@imiona"; # wypisyje elementy oddzielając je spacjami
print @imiona.""; # wypisuje ilość elementów tablicy
W specjalnej tablicy o nazwie @ARGV zapisane są wszystkie parametry podane w linii komend przy starcie programu. Aby wypisać pierwszy parametr napiszemy:
print("$ARGV[0]"); # wypisanie pierwszego parametru
Następujący program zakończy swe działanie komunikatem jeśli się okaże,
że został wywołany z jakimikolwiek parametrami:
if (@ARGV)
{
print "Program został wywołany z parametrami!\n";
}
Poza przedstawionymi już tablicami istnieją jeszcze tablice asocjacyjne (ang. associative array). Zasadniczą różnicą między tablicą, a tablicą asocjacyjną jest sposób odwoływania się do poszczególnych ich elementów - w zwykłej tablicy każdemu elementowi odpowiadała liczba, podczas gdy w wypadku tablic asocjacyjnych każdemu elementowi będzie przyporządkowany łańcuch.
W odróżnieniu od tablic, przed nazwami tablic asocjacyjnych stawiamy znak procenta. Tak można stworzyć tablicę asocjacyjną zawierającą liczby oznaczające wiek danych osób:
%wiek = ("kazik", 17,
"tomek", 20,
"marek", 31);
Aby odczytać interesującą nas informacje z wcześniej przygotowanej tablicy
asocjacyjnej napiszemy:
$wiek{"marek"} # to wyrażenie zwróci wartość 31
Ponieważ w tablicy zapisane są zmienne skalarne, do ich odczytu używamy
znaku dolara.
Możliwe jest konwertowanie zwykłych tablic na tablice asocjacyjne i na odwrót.
@tab = %wiek; # od tej chwili @tab = ("marek", "31", "tomek",
# "20", "kazik", "17");
%nowa = @tab # od tej chwili %nowa jest taką samą tablicą jak
# %wiek
Program wykonywany w systemie UNIX może odwoływać się do zmiennych środowiskowych, które często zawierają przydatne nam informacje. Spróbuj wydać polecenie "set" w twoim shellu, aby dowiedzieć się o aktualnie ustalonych zmiennych środowiskowych. Perl standardowo udostępnia nam cały zestaw tych zmiennych. Są one umieszczone w tablicy asocjacyjnej o nazwie %ENV.
print "Ty jesteś $ENV{'USER'}, witam!"; # zmienna USER zawiera aktualną
# nazwę użytkownika
Oto najważniejsze operacje jakim możemy poddać zmienne liczbowe (większość z nich pochodzi z języka C):
$x = 4 + 2; # dodawanie (w wyniku $x = 6)
$x = 4 - 2; # odejmowanie (w wyniku $x = 2)
$x = 4 * 2; # mnożenie (w wyniku $x = 8)
$x = 4 / 2; # dzielenie (w wyniku $x = 2)
$x = 4 ** 2; # potęgowanie (w wyniku $x = 16)
$x = 4 % 2; # reszta z dzielenia (w wyniku $x = 0)
++$a; # zwiększenie $a o jednostkę i zwrócenie wartości
$a++; # zwrócenie wartości $a i zwiększenie jej o jednostkę
--$a; # zmniejszenie $a o jednostkę i zwrócenie wartości
$a++; # zwrócenie wartości $a i zmniejszenie jej o jednostkę
A oto przykłady innych operacji, tym razem na łańcuchach:
$a = 'Lin';
$b = 'ux'; # "sklejenie" dwóch łańcuchów, zmienna $c będzie zawierać
$c = $a . $b; # słowo "Linux"
$a = 'masło';
$b = 10; # zmienna $c będzie zawierać łańcuch złożony z dziesięciu
$c = $a x $b; # "sklejonych" łańcuchów $a
Ustalać wartości zmiennych możemy na wiele sposobów. Dla przykładu przyjmujemy, że każde z poniższych przypisań jest wykonywane z osobna na zmiennych $a = 2 i $b = 3:
$a = $b # przypisanie $a do $b (w wyniku $a = 3, $b = 3)
$a += $b # dodanie $b do $a (w wyniku $a = 5, $b = 3)
$a -= $b # odjęcie $b od $a (w wyniku $a = -1, $b = 3)
$a .= $b # dopisanie $b do $a (w wyniku $a = 23, $b = 3)
Dzięki instrukcji "foreach" możemy przemieszczać się kolejno poprzez elementy tablicy lub kolejnych lini pliku tekstowego i wykonywać na nich operacje. Dla przykładu wykorzystamy tablicę "@imiona":
foreach $imie (@imiona) # Każdy kolejny element tablicy @imiona
# będzie chwilowo dostępny pod zmienną $imie
{
print "KTO : ";
print "$imie\n";
}
Nawiasy jakie pojawiły się powyżej "{}" są używane do określania bloku
programu, czyli zbioru instrukcji i wyrażeń. W tym akuratnie przypadku za
każdym podstawieniem pod zmienną "$imie" nowej wartości wykonywane są dwie
czynności (zawarte w bloku).
Rozważymy teraz kilka wyrażeń testujących. Testy porównują ze sobą zmienne lub wartości i mogą zwracać prawdę (ang. true) lub fałsz (ang. false). W Perlu zasadniczo każda liczba różna od zera i każdy łańcuch, który nie jest pusty jest uznawany za prawdę, a liczba 0 lub pusty łańcuch za fałsz. I tak:
$a == $b # prawda jeśli $a jest liczbowo równe $b
$a != $b # prawda jeśli $a jest liczbowo różne od $b
$a eq $b # prawda jeśli łańcuch $a jest taki sam jak $b
$a ne $b # prawda jeśli łańcuchy $a i $b się różnią
A tak używamy logicznych wartości "AND", "OR", "NOT":
($a && $b) # Czy $a i $b są prawdą ?
($a || $b) # Czy $a lub $b jest prawdą ?
!($a) # Czy $a to fałsz ?
Testy, przedstawione powyżej znajdują zastosowanie m.in. w instrukcjach warunkowych, których ogólna postać wygląda następująco:
if test1
{
operacja1;
}
elsif test2
{
operacja2;
}
else
{
operacja3;
}
Instrukcje takie działają na następującej zasadzie: Jeśli okaże się, że
"test1" wykazuje wartość prawda to zostaje wykonany pierwszy blok programu.
Jeśli "test1" się nie powiedzie, to zostaje przeprowadzony "test2" i jeśli
on się powiedzie wykonanywany jest odpowiedni blok operacji. Jedna
instrukcja warunkowa może zawierać wiele członów "elsif". Następny człon
instrukcji (zaczynający się od słowa "else") dotyczy przypadku, w którym
żaden z wcześniejszych testów się nie powiódł. W najprostszym przypadku
człony "elsif" i "else" nie muszą się w ogóle pojawić.
Przykładowo ta instrukcja warunkowa sprawdzi, czy łańcuch "$a" jest pusty, czy też zawiera jeden, dwa, a może więcej znaków i wypisze odpowiedni komunikat:
if (!$a) # Czy łańcuch $a zwraca wartość fałsz ?
{
print "Łańcuch jest pusty.\n";
}
elsif (length($a) == 1) # Czy łańcuch $a ma jeden znak ?
{
print "Łańcuch składa się z jednego znaku.\n";
}
elsif (length($a) == 2) # Czy łańcuch $a ma dwa znaki ?
{
print "Łańcuch składa się z dwóch znaków.\n";
}
else # Gdy ilość znaków > 2
{
print "Łańcuch składa się z wielu znaków.\n";
}
Za pomocą instrukcji "unless" możemy w trochę inny sposób sprawdzać prawdziwość testów i na podstawie ich wyników wykonywać stosowne operacje.
operacja unless test; # Wykonaj operacje, chyba że test zwraca
unless test operacja; # wartość prawda
Przykładowo:
die unless ($l); # zakończ działanie programu jeżeli zmienna $l jest
# pusta
Poznamy teraz zasadę budowania podstawowej pętli "for", pochodzącej bezpośrednio z języka C. Ma ona postać:
for (inicjalizacja; test; zmiana_wartości)
{
operacja;
}
Na początku pętli "for" wykonywane jest wyrażenie "inicjalizacja",następnie
przeprowadzany jest "test" i jeśli zwróci on wartość prawda, to zostaje
wykonany blok operacji, następnie wykonana zostaje "zmiana_wartości", która
najczęściej polega na zwiększeniu o jednostkę zmiennej ustalonej podczas
"inicjalizacji". "Zmiana_wartości" jest wyrażeniem wykonywanym w każdym
przebiegu pętli. Pętla jest wykonywana dopóki "test" nie zwróci wartości
fałsz. Oto przykład pętli, która wypisze cyfry od 0 do 9:
for ($a = 0; $a < 10; ++$a)
{
print "$a\n";
}
Inny sposób zapętlania uzyskujemy dzięki konstrukcji while. Ogólnie jej postać przedstawia się następująco:
while test
{
operacje;
}
continue
{
operacje;
}
Działanie jej polega na ciągłym wykonywaniu bloku operacji jeśli tylko
"test" zwraca wartość prawda. Drugi człon (po słowie "continue") nie jest
niezbędny, a jego rola jest taka sama jak elementu "zmiana_wartości" w pętli
"for" - wyrażenie to jest wykonywane w każdym przebiegu pętli.
Oto przykład pętli "while", która pyta użytkownika o wynik działania matematycznego i będzie powtarzać pytanie dopóki nie uzyska poprawnej odpowiedzi:
print 'Ile to jest 2*2, hmm ? ';
$a = <STDIN>; # Tak czytamy dane ze standardowego wejścia
chop($a); # odcięcie znaku końca linii
while($a ne 4) # powtarzaj dopóki użytkownik nie poda dobrego
wyniku
{
print "Niestety to zły wynik!\nSpróbuj ponownie : ";
$a = <STDIN>;
chop($a);
}
print "Jakoś Ci się udało.\n";
W Perlu, jak w większości innych języków istnieje instrukcja "goto", pomimo tego że można ją w każdym przypadku z powodzeniem zastąpić pętlami i jej nadużywanie nie należy do kunsztu programistycznego. Jej postać jest następująca:
operacje;
label:
operacje;
goto label;
Instrukcja powoduje zatrzymanie programu i przeskok do punktu, w którym
został umieszczony znacznik (ang. label). Na przykład następujący program
po uruchomieniu będzie wypisywał na ekranie dane słowo w nieskończoność:
re: # oznanaczenie punktu w programie
print " HEJ ! "; # dalszy ciąg programu
goto re; # przeskok do oznaczonego punktu
W Perlu budowanie instrukcji jest dosyć dowolne. Ten sam efekt bardzo
często możemy uzyskać na kilka sposobów i wybranie jednego z nich zależy
tylko i wyłącznie od własnych upodobań.
Oto przykładowy program obliczający sumę algebraiczną z podanych liczb, wykorzystuje on poznane już instrukcje:
do # tak też można
{
print "Proszę podać liczbę : ";
$liczba = <STDIN>;
$efekt += $liczba;
++$numer;
}
until ($liczba eq "\n");
if ($numer != 0)
{
$sr = $efekt / $numer;
print "Średnia arytmetyczna podanych liczb : $sr\n";
}
Ten przykładowy program natomiast służy do odnajdywania liczb pierwszych
(według naiwnego algorytmu):
print "Proszę podać liczbę : ";
$l = <STDIN>;
chop($l);
for($i = 2; $i < $l; $i++)
{
if (($l % $i) == 0)
{
print "Liczba $l nie jest pierwsza!\n";
exit;
}
}
print "Liczba $l jest pierwsza!\n";
Każdy plik przed zapisem lub odczytem należy otworzyć, a po zakończeniu operacji na nim zamknąć. Do otwarcia pliku dyskowego w języku Perl służy funkcja "open", zaś do zamknięcia "close". Schemat obsługi pliku jest prosty:
open(DANE, ścieżka_do_pliku); # otwarcie pliku (DANE to przykładowa nazwa)
[ ... ] # operacje na nim
close(DANE); # zamknięcie pliku
Plik może zostać otwarty na kilka sposobów:
open(DANE, ścieżka_do_pliku); # otwarcie pliku do odczytu
lub
open(DANE, "<ścieżka_do_pliku");
open(DANE, ">ścieżka_do_pliku"); # otwarcie pliku do zapisu
open(DANE, ">>ścieżka_do_pliku"); # otwarcie pliku do dopisywania
Czasem przydatne są rozszerzenia shella umożliwjające łatwiejszą lokalizację
potrzebnych plików na dysku. Na przykład chcąc otworzyć plik znajdujący się
w katalogu domowym użytkownika napiszemy:
open(DANE, <~/plik.txt>);
Najprostszym przypadkiem wyprowadzania danych z pliku będzie wczytanie do
tablicy całej zawartości pliku tekstowego:
open(DANE, '/etc/passwd'); # otwarcie pliku do odczytu
@tekst = <DANE>; # zapisanie tekstu z pliku w tablicy (każda
# linia będzie jednym elementem tablicy
@tekst)
close(DANE); # zamknięcie pliku
A tak zapisujemy tekst do pliku:
open(DANE, '>dane.txt'); # otwarcie do zapisu
print DANE "Tekst zapisywany do pliku.\n"; # zapisanie tekstu do pliku
close(DANE); # zamknięcie pliku
Za pomocą funkcji open możemy także otwierać i zamykać standardowe wejście
(najczęściej klawiatura) i wyjście (najczęściej ekran).
open(DANE, '-'); # otwarcie standardowego wejścia
open(DANE, '>-'); # otwarcie standardowego wyjścia
Operowanie na łańcuchach w Perlu jest jedną z jego mocnych stron. Perl oferuje duże możliwości w tej dziedzinie. Na początek podam sposób sprawdzania, czy dane wyrażenie występuje lub nie występuje w przeszukiwanym łańcuchu:
$s =~ /Ala/ # wyrażenie to zwraca wartość prawda, gdy łańcuch $s zawiera
# szukane słowo zawarte w slashach.
$s !~ /Ala/ # wyrażenie to zwraca wartość prawda, gdy łańcuch $s nie
# zawiera szukanego słowa zawartego w slashach.
Nadażyła się dobra okazja, aby przedstawić zmienną $_, która jest domyślną zmienną dla wielu funkcji - operacje wykonywane są na niej jeśli inna zmienna nie została wyspecyfikowana (skraca to nieco kod i eliminuje zbyt dużą liczbę zmiennych). Ten zapis:
$s = 'Ala ma kota.';
if ($s =~ /Ala/)
{
print 'Odnaleziono wyraz Ala !';
}
Jest równoważny następującemu:
$_ = 'Ala ma kota.';
if (/Ala/)
{
print 'Odnaleziono wyraz Ala !';
}
Wyszukując w danym łańcuchu konkretny zapis korzysta się z wielu znaków specjalnych umieszczanych wewnątrz slashów:
. # jakikolwiek znak oprócz znaku nowej linii (\n)
^ # rozpoczęcie nowej linii lub łańcucha
$ # koniec linii lub łańcucha
* # dowolna ilość powtórzeń ostatniego znaku
+ # jeden lub więcej powtórzeń ostatniego znaku
? # brak lub jedno wystąpienie ostatniego znaku
Za pomocą powyższych znaków specjalnych można budować maski i porównywać je
ze zmiennymi. Oto kilka przykładowych masek:
.* # łańcuch składający się z dowolnych znaków oprócz znaków końca lini
^$ # pusta linia
.*x$ # dowolny ciąg znaków, który kończy się literą "x" na końcu lini
Zwykłych nawiasów "()" możemy używać do grupowania znaków,
na przykład:
(.*)* # dowolna ilość dowolnych łańcuchów
(^$)+ # jedna lub więcej pustych lini
(.*x$)* # dowolna ilość łańcuchów zakończonych literą "x" na końcu lini
Jeśli chcemy odnaleźć którykolwiek znak spośród kilku należy je umieścić w
nawiasach kwadratowych "
[abc] # którykolwiek ze znaków, "a", "b" lub "c"
[^abc] # przeczenie - ani "a", ani "b", ani "c"
[a-z] # jakiekolwiek znaki od "a" do "z"
[^a-z] # jakiekolwiek znaki oprócz znaków "a" do "z"
Nawiasy klamrowe "{}" służą do określania ilości powtórzeń wystąpienia
łańcucha:
(.*){3} # trzy dowolne łańcuchy
(^$){3,} # przynajmniej trzy dowolne łańcuchy
(.*x$){3,5} # przynajmniej trzy, ale nie więcej niż pięć łańcuchów
# zakończonych literą "x" na końcu lini
Aby w masce zawrzeć znaki, które mają pierwotnie swoje znaczenie w języku
(np. ^) należy je poprzedzić backslashem ("\"). Na przykład:
\^
\$
\*
Ponadto w masce niektóre litery zapisane z backslashem na początku nabierają
specjalnego znaczenia:
\n # znak nowej lini
\t # tabulator
\a # alarm
\l # następny znak ma być "małą" literą
\u # następny znak ma być "dużą" literą
\L # następne znaki, aż do wystąpienia \E mają być "małymi" literami
\U # następne znaki, aż do wystąpienia \E mają być "dużymi" literami
\E # zakańcza modyfikacje "wielkości" liter
\w # pojedyńczy znak alfanumeryczny
\W # jakikolwiek znak nie będący znakiem alfanumerycznym
\s # spacja
\S # jakikolwiek znak nie będący spacją
\d # liczba
\D # jakikolwiek znak nie będący liczbą
Na przykładzie pokaże sposób wyłuskiwania pewnych części łańcuchów za pomocą
porównywania ich z maskami:
$_ = 'linux Operating system';
/([A-Z][a-z]+\s)+/; # wykorzystanie właściwości zmiennej $_
Po wykonaniu takiej operacji do naszej dyspozycji zostaje oddany szereg
pseudo-zmiennych (można je tylko czytać, nie zapisywać). Jak widać maska,
której użyliśmy opisuje słowo "Operating", w zmiennej $& odnajdziemy więc
właśnie to słowo, pod zmienną $` natomiast zapisane zostanie słowo "linux", a
pod $' słowo "system". Dzięki temu faktowi jesteśmy w stanie wyłuskać
potrzebną nam część łańcucha.
Przy przeszukiwaniu łańcuchów wszystkie odnalezione wyrażenia zawarte w zwykłych nawiasach są zapamiętywane w pseudo-zmiennych $1, $2, $3 itd. Można je także wykorzystać w ramach aktualnie wykonywanej funkcji odwołując się do nich poprzez \1, \2, \3 itd.
$_ = 'Linux Operating System';
if (/(.*ux)/)
{
print "$1\n"; # znaleziony łańcuch (Linux)
}
Bardzo pomocną funkcją wykorzystującą maski jest s/// wraz z jej opcjami. Służy ona do podmieniania zawartości jednego wyrażenia innym.
s/linux/Linux/ # przeszukiwany jest łańcuch $_, gdy okaże się, że
# zawiera on wyrażenie "linux" zostanie ono
# podmienione na łańcuch "Linux".
s/linux/Linux/g # przeszukiwany jest łańcuch $_, wszystkie
# wystąpienia wyrażenia "linux" zostaną podmienione
# na łańcuch "Linux"
s/linux/Linux/gi # przeszukiwany jest łańcuch $_, wszystkie
# wystąpienia wyrażenia "linux" (niezależnie od
# wielkości liter np. LiNux, linuX itd.) zostaną
# podmienione na łańcuch "Linux"
Konkretny przykład zastosowania funkcji s///:
$_ = 'Linux Operating System';
s/(A-Z)/:\1:/g; # każda wielka litera zostanie zawarta w
# dwukropkach (:L:inux :O:perating :S:ystem)
Do podmieniania znaków innymi znakami służy funkcja tr///. Na przykład:
$_ = 'LinuX';
tr/A-Z/a-z/g; # podmienienie wszystkich dużych liter na
# małe (w efekcie dostajemy słowo "linux")
$_ = 'linux';
tr/x/s/; # podmienienie litery "x" na "s" (w efekcie "linus")
Przydatną funkcją Perla jest split. Pozwala ona na rozbicie łańcucha i umieszczenie poszczególnych jego części w tablicy:
$s = 'kazik:tomek:marek';
@tab = split(/:/, $s);
Wykonując taką operację otrzymujemy poszczególne części łańcucha, które w
łańcuchu $s były ograniczone znakiem ":", zapisane w kolejnych elementach
tablicy. Efekt działania funkcji split wygląda tak:
@tab = ("kazik", "tomek", "marek");
Oczywiście w miejsce pojedyńczego znaku ":" możemy wprowadzić dowolne maski,
które będą opisywać wyrażenia oddzielające od siebie szukane łańcuchy.
Funkcja split może także być stosowana w krótszej postaci (operować na
zmiennej $_):
$_ = 'Linux, Operating System';
@tab = split(/.*\s/);
W efekcie otrzymamy tablicę @tab, składającą się z trzech wyrazów (Linux,
Operating, System) zapamiętanych w kolejnych jej polach.
Funkcja substr pozwala na wycinanie części łańcucha. Posługując się nią podajemy offset, w którym rozpoczyna się szukana część łańcucha i ewentualnie jej długość.
$s = substr('Ala ma kota', 2, 6); # łańcuch $s będzie równy "a ma k"
^ ^
$s = substr('Ala ma kota', 6); # łańcuch $s będzie równy "kota"
^
$s = substr('Ala ma kota', -4, 3); # łańcuch $s będzie równy "kot"
^ ^
Jak w prawie każdym języku tak i w Perlu możemy zapisać część kodu w postaci procedur i odwoływać się do niego w późniejszym biegu programu. Procedury zawarte w programie składają się ze słowa kluczowego sub i bloku operacji:
sub moja
{
print "To moja procedura.";
}
Przykładowo, tak zapisaną procedurę możemy wywoływać w dalszej części
programu:
while (true) # pętla nieskończona
{
&moja; # wywołanie procedury
}
Do procedur możemy przekazywać zmienne pochodzące z innych części programu
wywołując ją w następujący sposób:
&moja(12); # wywołanie procedury z jednym parametrem
moja(12, $_); # wywołanie procedury z parametrami
Prosta procedura, którą stworzyliśmy nie reaguje w żaden sposób na
przekazywane jej zmienne. We wnętrzu procedury możemy się dostać do tych
zmiennych poprzez tablicę o nazwie @_:
sub moja2
{
print "Procedura została wywołana z następującymi parametrami :\n";
print @_;
}
Jej wywołanie:
&moja2("karmazynowy pirat", "Linux"); # procedura odczyta przekazane jej
# zmienne i wyświetli je.
Stworzone przez nas procedury także zwracają wartości.
sub moja3
{
if ($_[0] > $_[1])
{
$_[0];
}
else
{
$_[1];
}
}
Procedura moja3 wywołana z dwoma zmiennymi sprawdza, która z nich jest
większa i zwraca jej wartość. A oto jej konkretne zastosowanie:
$większa = &moja3(12, 32); # zmienna $większa będzie równa 32
Kazimierz Pietruszewski Jr