Pri obrashchenii k elementu, nahodyashchemusya za predelami massiva, budet
vozvrashcheno znachenie undef, pri prisvaivanii znacheniya takomu elementu massiv
avtomaticheski uvelichitsya, a vse promezhutochnye elementy poluchat znachenie
undef.
Inicializiruyutsya massivy spisochnymi dannymi, kotorye zapisyvayutsya v
vide zaklyuchennoj v kruglye skobki posledovatel'nosti znachenij, otdelennyh
drug ot druga zapyatymi:
@a = (0, $a, 5, "123", @b);
Pri etom vstavlennye takim obrazom elementy massiva @b nahodyatsya na tom
zhe urovne ierarhii, chto i drugie elementy spiska, t.e. prosto dopisyvayutsya v
konec massiva @a.
Prisvaivanie spiskov pozvolyaet osushchestvlyat' dovol'no lyubopytnye
operacii:
($a, $b, $c, @e) = ($b, $a, @g);
$a i $b obmenyayutsya znacheniyami, $c budet prisvoeno znachenie pervogo
elementa massiva @g, ostal'nye elementy budut skopirovany v massiv @e.
Srez massiva pozvolyaet vybrat' iz nego za odin raz neskol'ko elementov:
@a[0, 1, 10];
|tu zhe operaciyu mozhno primenit' k spisku:
($a, $b, $c, $d)[0, 1];
|ta tehnika ispol'zuetsya, k primeru, dlya polucheniya informacii o
vremeni: funkciya localtime preobrazuet rezul'tat, vozvrashchaemyj funkciej time
(vremya v sekundah ot 1.01.1970), v zavisimosti ot konteksta, libo v stroku
vida "Fri Sep 15 11:12:13 2000", libo v massiv iz devyati elementov (sekundy,
minuty, chasy, den', mesyac, god, den' nedeli, den' goda, priznak letnego
vremeni):
($day, $month, $year) = (localtime(time))[3, 4, 5];
Sleduet otmetit', chto mesyacy, dni goda i dni nedeli nachinayutsya s nulya,
prichem nulevym dnem nedeli schitaetsya voskresen'e, a gody schitayutsya ot 1900
goda. Takim obrazom, 2000 godu sootvetstvuet znachenie 100 (iz-za togo, chto
mnogie programmisty zabyli etot fakt, v nachale 2000 goda na raznyh stranicah
seti mozhno bylo nablyudat' datu vida 1.01.100 ili 1.01.19100).
Pri zapisi spiskov vmesto operacii "," mozhno vospol'zovat'sya => :
zapis' ("one", 1, "two", 2, "three", 3) ekvivalentna (one => 1, two
=>2, three => 3), chto mozhet sdelat' spisok bolee naglyadnym.
Dlya raboty s massivom kak so stekom ispol'zuyutsya funkciya push,
dobavlyayushchaya elementy (odin ili neskol'ko) v konec massiva, i funkciya pop,
udalyayushchaya poslednij element. Dlya raboty s nachalom massiva ispol'zuyutsya
analogichnye funkcii unshift i shift. Po umolchaniyu vse eti funkcii rabotayut s
vstroennym massivom @_.
Funkciya reverse menyaet poryadok sledovaniya elementov spiska-argumenta na
obratnyj i vozvrashchaet rezul'tat. Funkciya sort po umolchaniyu sortiruet
argumenty po vozrastaniyu, rassmatrivaya ih kak strokovye peremennye.
Pomimo prostyh massivov, v Perl sushchestvuyut associativnye massivy, ili
heshi. Ih otlichie ot prostyh massivov v tom, chto indeksami yavlyayutsya ne
posledovatel'nye celye chisla, a proizvol'nye skalyarnye velichiny.
Inicializiruyutsya heshi spiskom, chetnye elementy kotorogo (nachinaya s nulya),
yavlyayutsya indeksom, chetnye -- znacheniem, i nachinayutsya s simvola %:
%a = (one => 1, two =>2, three => 3);
Dostup k elementu hesha zapisyvaetsya kak $a{1} (v nashem primere vernet
"one").
Funkciya key vozvrashchaet spisok klyuchej peredannogo ej hesha, funkciya
values -- spisok znachenij. Funkciya each posledovatel'no prohodit po heshu,
vozvrashchaya paru klyuch-znachenie v vide spiska iz dvuh elementov. Udalit'
element hesha mozhno funkciej delete:
delete $a{1};
Predstavit' sebe sovremennyj yazyk programmirovaniya, ne imeyushchij
ssylochnyh tipov dannyh, nevozmozhno. Ne obdelen imi i Perl. Zdes' mozhno
poluchit' ssylku na lyuboj iz vstroennyh tipov, i prisvoit' ee nekotoroj
skalyarnoj peremennoj:
$ref1 = \$var;
$ref2 = \@array;
$ref3 = \%hash;
Dlya dostupa k skalyarnym peremennym, na kotoryh ssylaetsya ssylka, mozhno
vospol'zovat'sya sleduyushchimi konstrukciyami:
$$ref1;
${$ref1};
$ref2->[12];
${$ref2}[12];
$$ref2[12];
$ref3->{$key};
${$ref3}{$key};
$$ref3{$key};
Kak pravilo, predpochitayut ispol'zovat' konstrukcii s operatorom ->,
delayushchie kod bolee chitabel'nym.
Mozhno takzhe sozdat' ssylku na anonimnyj massiv ili hesh:
$aref = [1, 2, 3];
$href = {1 => One, 2 => Two, 3 => Three};
S pomoshch'yu ssylok mozhno formirovat' dovol'no slozhnye struktury dannyh
(naprimer, massiv ssylok na heshi).
Upravlyayushchie struktury i funkcii
Dlya upravleniya potokom ispolneniya programmy ispol'zuyutsya operatory
vetvleniya i cikla, analogichnye sushchestvuyushchim v S. Prichem obyazatel'nym
usloviem yavlyaetsya ispol'zovanie bloka operatorov, zaklyuchennyh v figurnye
skobki. Poslednij operator v bloke mozhet ne imet' zavershayushchej tochki s
zapyatoj:
if($a>$max) {$max = $a}
Obshchaya forma operatora if:
if(uslovie 1)
{...}
elsif(uslovie 2)
{...}
elsif(uslovie 3)
{...}
...
else
{...}
Vmesto konstrukcii if(!uslovie) mozhno ispol'zovat' unless(uslovie), a
dlya uproshcheniya zapisi vmesto konstrukcii if(uslovie){operator} mozhno
ispol'zovat' operator if uslovie.
V kachestve upravlyayushchih struktur chasto ispol'zuyutsya operacii && i ||:
Zapis' if(vyrazhenie){operator} ekvivalentna zapisi vyrazhenie &&
operator, a zapis' unless (vyrazhenie){operator} -- zapisi vyrazhenie ||
operator. Vybor toj ili inoj formy polnost'yu zavisit ot nastroeniya
programmista.
Operatory cikla takzhe chut' bolee raznoobrazny, chem v S: vmesto
while(!uslovie){} mozhno zapisat' until(uslovie){}, analogichno i dlya cikla s
post-usloviem. Dlya sokrashcheniya zapisi takzhe ispol'zuetsya konstrukciya operator
while vyrazhenie.
Pomimo operatora for, nichem ne otlichayushchegosya ot S, sushchestvuet operator
foreach, kotoryj zapisyvaetsya kak
foreach $i(@spisok)
{}
V etom sluchae skalyarnaya peremennaya $i posledovatel'no prinimaet
znacheniya elementov spiska. Naprimer, perebrat' vse elementy hesha,
otsortirovannye po klyucham, mozhno tak:
foreach $i(sort keys %a)
{
print $a{$i}."\n";
}
Pri prohode po bol'shomu heshu effektivnee ispol'zovat' funkciyu each --
cenoj poteri sortirovki:
while(($key, $value) = each(%a))
{
}
Dlya vseh operatorov cikla, krome cikla s post-usloviem, sushchestvuyut
operatory last, preryvayushchij vypolnenie cikla, next, perehodyashchij k sleduyushchej
iteracii, i redo, obespechivayushchij perehod v nachalo tekushchego bloka bez
proverki usloviya. Ih mozhno ispol'zovat' v sochetanii s metkami:
OUTER: while(uslovie 1)
{
INNER: while(uslovie 2)
{
if(uslovie 3)
{
next OUTER; #perehod na sleduyushchuyu iteraciyu vneshnego cikla
}
}
}
Funkcii zapisyvayutsya sleduyushchim obrazom:
sub f
{
}
i vyzyvayutsya kak f();
Znachenie iz funkcii vozvrashchaetsya operatorom return, pri otsutstvii ego
vozvrashchaemym znacheniem yavlyaetsya rezul'tat poslednej vyrazheniya, vychislennogo
v funkcii. Pri peredache parametrov v funkciyu oni zanosyatsya vo vstroennuyu
peremennuyu @_, dostup k elementam kotoroj mozhno poluchit' kak k elementam
obychnogo massiva: $_[0] i t.p., a takzhe cherez funkcii shift, pop i t.p.
Takim obrazom, funkcii mogut imet' peremennoe kolichestvo parametrov.
Peremennye, ispol'zuemye v funkciyah, po umolchaniyu imeyut global'nuyu
oblast' vidimosti:
sub f
{
$a++;
}
$a = 1;
f();
print $a; # napechataet 2
Dlya togo, chtoby sdelat' peremennuyu lokal'noj, nado ob座avit' ee s
pomoshch'yu operatora my:
sub f
{
my $a;
$a++;
}
$a = 1;
f();
print $a; # napechataet 1
Rasprostranennym priemom yavlyaetsya inicializaciya parametrov funkcii,
imeyushchih osmyslennye imena:
my($param1, $param2) = @_;
Pri nalichii direktivy use strict ob座avlenie peremennyh s pomoshch'yu
operacii my yavlyaetsya obyazatel'nym.
Krome direktivy my sushchestvuet pohozhaya na nee direktiva local. Raznica
mezhdu nimi sleduyushchaya: my ogranichivaet oblast' dejstviya peremennoj tekushchim
blokom, local zhe delaet etu peremennuyu dostupnoj i vo vseh funkciyah, kotorye
vyzyvayutsya iz tekushchego bloka.
Teper', nauchivshis' rabotat' s funkciyami, my mozhem ispol'zovat'
sortirovku s proizvol'nym kriteriem.
sub by_num
{
return $a <=> $b;
}
foreach $i(sort by_num keys %a)
{
print $a{$i}."\n";
}
Funkciya by_num opredelyaet kriterij sortirovki, a peremennye $a i $b,
peredavaemye v nee, yavlyayutsya vstroennymi i lokal'nymi dlya nee peremennymi.
To zhe samoe mozhno zapisat' eshche koroche, ispol'zuya anonimnuyu funkciyu:
foreach $i(sort {$a <=> $b} keys %a)
{
print $a{$i}."\n";
}
Mozhno sozdat' ssylku na funkciyu:
sub func{...}
$fref1 = \&func;
$fref2 = sub {...}; # Ssylka na anonimnuyu funkciyu
Ispol'zuetsya eta ssylka kak $fref1->(spisok argumentov).
Vvod-vyvod
Vvod s konsoli osushchestvlyaetsya s pomoshch'yu operatora <STDIN>:
$a = <STDIN>; # schityvaet sleduyushchuyu stroku do simvola
#perevoda stroki
# (tochnee, do znacheniya, prisvoennogo peremennoj $/)
# libo undef, esli strok bol'she net
@a = <STDIN>; # schityvaet vse stroki do zaversheniya vvoda (obychno --
# nazhatie Ctrl-Z); kazhdaya strochka budet zavershat'sya
# simvolom perevoda stroki
while(<STDIN>) {...} #posledovatel'no schityvaet stroki v
#vstroennuyu peremennuyu $_.
Vyvod na konsol' osushchestvlyaetsya s pomoshch'yu funkcii print,
formatirovannyj vyvod -- s pomoshch'yu printf, polnost'yu analogichnoj
sootvetstvuyushchej funkcii S. Esli u print ne ukazan parametr, vyvoditsya
soderzhimoe vstroennoj peremennoj $_.
Dlya vvoda iz fajlov, perechislennyh v komandnoj stroke skripta,
ispol'zuetsya operaciya <>:
while(<>){...}
Esli v kachestve parametrov peredano neskol'ko imen fajlov, operaciya <>
schitaet ih vseh posledovatel'no.
Dlya fajlovogo vvoda-vyvoda snachala neobhodimo svyazat' s fajlom
deskriptor. Standartnye deskriptory STDIN, STDOUT, STDERR uzhe svyazany so
standartnym vvodom, standartnym vyvodom i standartnym vyvodom oshibok, krome
togo, sushchestvuet special'nyj deskriptor DATA, pozvolyayushchij schitat' tekst,
sleduyushchij posle simvolov __END__ iz fajla, v kotorom nahoditsya sama
programma.
Dlya otkrytiya dopolnitel'nyh deskriptorov ispol'zuetsya funkciya open:
open(FILE1, "filename"); # otkryvaet fajl dlya chteniya
open(FILE2 ">filename"); # otkryvaet fajl dlya zapisi
open(FILE3, ">>filename"); # otkryvaet fajl dlya dobavleniya
Pri neudachnom otkrytii fajla funkciya open vozvrashchaet znachenie "lozh'",
tak chto pravilom horoshego tona yavlyaetsya proverka etogo znacheniya:
open (FILE, "filename") || die "cannot open file: $!";
Funkciya die vyzyvaet avarijnoe zavershenie programmy, peremennaya $!
soderzhit stroku s opisaniem poslednej oshibki.
Posle zaversheniya raboty fajl neobhodimo zakryt':
close (FILE);
Imena deskriptorov ne nachinayutsya s kakih-to special'nyh simvolov, i
obshcheprinyato vvodit' ih zaglavnymi bukvami -- prosto, chtoby otlichit' ot
obychnyh peremennyh.
Dalee ih mozhno ispol'zovat' v sochetanii s operaciej <> dlya vvoda:
@a = <FILE>; # Ckladyvaet vse strochki fajla v massiv strok. Mozhet
# okazat'sya ne samym luchshim resheniem, esli fajl imeet
# bol'shoj razmer
Dlya vyvoda v otkrytyj fajl ego deskriptor zapisyvaetsya srazu posle
klyuchevogo slova print. Zapyatoj mezhdu deskriptorom i drugimi argumentami byt'
ne dolzhno:
print FILE "some text\n";
Dlya proverki sushchestvovaniya fajla ispol'zuetsya operaciya "-e": if(-e
$filename){...}. Sushchestvuyut takzhe operacii dlya proverki, dostupen li etot
fajl dlya chteniya (-r), dostupen li dlya zapisi (-w), yavlyaetsya li on katalogom
(-d) ili obychnym fajlom (-f) i t.d.
Ves'ma udobnoj yavlyaetsya vstroennaya v Perl podderzhka DBM-fajlom,
pozvolyayushchaya svyazat' associativnyj massiv s DBM-bazoj. Rodnaya dlya Unix-sistem
biblioteka DBM predostavlyaet v rasporyazhenie programmista prostuyu i udobnuyu
bazu dannyh. Sushchestvuyut razlichnye realizacii DBM, razlichayushchiesya vozmozhnym
razmerom zapisi, bazy, skorost'yu raboty i t.p. V prostejshem variante svyaz'
hesha s DBM-fajlom osushchestvlyaetsya funkciej dbmopen, a zakryvaetsya DBM-fajl
funkciej dbmclose:
dbmopen(%A, "basename", 0644)
dbmclose(%A);
Tretij parametr funkcii dbmopen ukazyvaet, s kakimi pravami dostupa
sozdavat' fajl, esli ego ne sushchestvuet. Esli net neobhodimosti sozdavat'
fajl, vmesto etogo parametra mozhno peredat' undef.
Dlya bolee polnoj informacii vospol'zujtes' komandoj perldoc
AnyDBM_File.<u></u>
Regulyarnye vyrazheniya
Regulyarnye vyrazheniya horosho znakomy opytnym pol'zovatelyam Unix, oni
ispol'zuyutsya dlya obrabotki teksta vo mnogih Unix-utilitah, takih kak grep,
awk, sed, v redaktorah (vi, emacs), v nekotoryh komandnyh obolochkah i t. d.
Regulyarnoe vyrazhenie predstavlyaet soboj obrazec, ili shablon, kotoryj
sopostavlyaetsya so strokoj. |to sopostavlenie, ili poisk po shablonu, mozhet
zakonchit'sya uspehom, ili neudachej. Krome togo, sovpadayushchij obrazec mozhet
byt' zamenen drugoj strokoj ili skopirovan vo vneshnyuyu peremennuyu.
Po umolchaniyu regulyarnye vyrazheniya ispol'zuyut vstroennuyu peremennuyu $_,
no mozhno sopostavit' s shablonom lyubuyu druguyu skalyarnuyu peremennuyu s pomoshch'yu
operatorov =~ i !~:
/tekst/; # vozvrashchaet istinu, esli v $_ soderzhitsya
# podstroka "tekst"
$s =~ /tekst/; # vozvrashchaet istinu, esli v $s soderzhitsya
# podstroka "tekst"
$s !~ /tekst/; # vozvrashchaet istinu, esli v $s net podstroki "tekst"
Dlya zameny podstroki, sootvetstvuyushchej shablonu, ispol'zuetsya zapis' vida
s/tekst1/tekst2/;
Vozmozhno ispol'zovanie modifikatorov, naprimer:
/tekst/i; # ignorirovat' registr
s/$s/tekst/g; # proizvodit' global'nuyu zamenu
V privedennyh primerah my ispol'zovali prostejshij obrazec, sostoyashchij iz
posledovatel'nosti obychnyh simvolov. Odnako vozmozhny i bolee slozhnye
kombinacii. Samyj prostoj simvol sopostavleniya -- tochka ("."). Ona
sootvetstvuet lyubomu odinochnomu simvolu, krome simvola novoj stroki. Mozhno
zadat' klass simvolov sopostavleniya s pomoshch'yu spiska, zaklyuchennogo v
kvadratnye skobki:
/[abvgde]/;
|tomu obrazcu sootvetstvuet stroka, soderzhashchaya odin iz etih shesti
simvolov. Diapazon simvolov zadaetsya s pomoshch'yu defisa (sam defis vstavlyaet v
spisok kak \-), simvol "^", stoyashchij srazu za otkryvayushchej skobkoj, oznachaet
otricanie -- takomu klassu simvolov sootvetstvuet lyuboj simvol,
otsutstvuyushchij v etom spiske. Nekotorye rasprostranennye klassy simvolov
imeyut predopredelennye oboznacheniya:
\d [0-9] cifra
\w [a-zA-Z0-9_] obychnyj simvol
\s [ \r\t\n\f] probel'nyj simvol
\D [^0-9] necifrovoj simvol
\W [^a-zA-Z0-9_] special'nyj simvol
\S [^ \r\t\n\f] neprobel'nyj simvol
Odnako samoe interesnoe nachinaetsya pri rabote s obrazcami dlya grupp
simvolov, ili mnozhitelyami. Dva osnovnyh obrazca zdes' -- zvezdochka "*" i
plyus "+". Zvezdochke sootvetstvuet ni odnogo ili bolee ekzemplyarov stoyashchego
pered nej simvola ili klassa simvolov, plyusu -- odin ili bolee ekzemplyarov.
Obrazcu "?" sootvetstvuet ni odnogo ili odin simvol, stoyashchij pered nim v
shablone, nakonec, s pomoshch'yu figurnyh skobok mozhno zadat' tochnoe kolichestvo
povtorenij etogo simvola, ili diapazon.
/ab*/; # stroki, soderzhashchie a, ab, abb, abbb i t.d.
/ab+/; # ab, abb, abbb i t.d.
/ab?/; # a, ab
/ab{2}/; # abb
/ab{2,4}/; # abb, abbb, abbbb
/ab{2,}/; # abb, abbb, abbbb i t.d.
Poisk po shablonu s mnozhitelyami harakterizuetsya tremya osobennostyami:
"zhadnost'yu", "toroplivost'yu" i vozvratom. "ZHadnost'" oznachaet, chto esli
shablon mozhet sovpast' so strokoj v neskol'kih variantah, to vybiraetsya samyj
dlinnyj:
$s = 'abbbbb';
$s =~ s/a.*b/c/; #rezul'tiruyushchaya stroka budet soderzhat' tol'ko "s".
Lyuboj mnozhitel' mozhno prevratit' iz "zhadnogo" v "lenivyj", postaviv
srazu posle nego voprositel'nyj znak:
$s = 'abbbbb';
$s =~ s/a.*?b/c/; #rezul'tiruyushchaya stroka soderzhit "cbbbb".
"Toroplivost'" oznachaet, chto mehanizm poiska stremitsya obnaruzhit'
sovpadenie kak mozhno skoree -- tak, shablonu /a*/ budet sootvetstvovat' lyubaya
stroka, poskol'ku * -- eto 0 ili bolee simvolov.
Nakonec, vozvrat obespechivaet sovpadenie so strokoj ne tol'ko chasti
regulyarnogo vyrazheniya, a vsego shablona. T.e. esli nachalo shablona sovpadaet
so strokoj, a odna iz posleduyushchih chastej -- net, mehanizm poiska
vozvrashchaetsya k nachalu i pytaetsya najti novoe sovpadenie.
Esli chasti shablona zaklyucheny v kruglye skobki, to vklyuchaetsya mehanizm
zapominaniya, i chasti stroki, kotorye im sootvetstvuyut, budut posledovatel'no
prisvaivat'sya peremennym $1, $2, $3 i t.p.:
$s = 'abbbbb';
$s =~ s/a(.*)b/c/; # v $1 budet nahodit'sya stroka "bbbb"
Drugoj sposob zapominaniya chasti stroki -- ispol'zovanie kodov \1, \2 i
t.p. neposredstvenno v shablone:
$s = 'abbbbb';
$s =~ s/a(.*)b/\1c/; # rezul'tiruyushchaya stroka soderzhit "bbbbc"
Vozmozhno ispol'zovanie odnogo iz neskol'kih shablonov:
/tekst1|tekst2|tekst3/
a takzhe ih kombinaciya s pomoshch'yu skobok:
/(a|b)c/;
CHtoby ne vklyuchat' zdes' rezhim zapominaniya, ispol'zuyut zapis'
/(?:a|b)c/;
Obrazec mozhet byt' zafiksirovan otnositel'no pozicii v stroke: /^a.*b$/
sootvetstvuet stroke, nachinayushchejsya s a i zakanchivayushchejsya b, a direktiva \b
trebuet, chtoby sovpadenie s obrazcom proishodila tol'ko na granice slova.
Esli v obrazce uchastvuet peremennaya, to pered sopostavleniem proishodit
ee interpolyaciya, takim obrazom, mozhno stroit' regulyarnoe vyrazhenie na
osnovanii stroki vvedennoj pol'zovatelem. CHut' pozzhe v etoj glave budet
pokazana opasnost' etogo podhoda, poka zhe otmetim, chto dlya otmeny
interpolyacii ispol'zuetsya upravlyayushchaya posledovatel'nost' \Q...\E,
predvaryayushchaya vse specsimvoly v stroke obratnoj kosoj chertoj i prevrashchayushchaya
ih tem samym v prostye simvoly:
/\Q$var\E/
Direktiva tr pozvolyaet zamenit' vse vhozhdeniya simvolov iz spiska v
stroke na drugie:
$s =~ tr/abcde/ABCDE/;
Parametr /e zastavlyaet rassmatrivat' zamenyayushchuyu stroku direktivy s kak
Perl-vyrazhenie:
$s =~ s/(.)/sprintf("[%s]", $1)/eg;
(bespoleznyj primer, rasstavlyayushchij kvadratnye skobki vokrug kazhdogo
simvola stroki i demonstriruyushchij rabotu funkcii formatnogo vyvoda v stroku
sprintf).
Regulyarnye vyrazheniya ochen' udobno ispol'zovat' dlya razbivki stroki na
sostavlyayushchie -- naprimer, znachenie, hranyashcheesya v DBM-fajle, udobno razbit'
na polya, symitirovav bolee slozhnuyu tablicu. Dlya etogo v Perl sushchestvuet
funkciya split. Pervyj ee parametr -- regulyarnoe vyrazhenie, rassmatrivayushcheesya
kak razdelitel' stroki, idushchej vtorym parametrom. Vse elementy stroki, ne
sovpadayushchie s regulyarnym vyrazheniem, posledovatel'no pomeshchayutsya v massiv,
vozvrashchaemyj funkciej split:
$s = 'abc:def:ghi';
@a = split(/:/, $s); # massiv @a budet soderzhat' tri elementa -- "abc",
"def", "ghi".
Esli ne ukazan vtoroj parametr, rabota idet s peremennoj $_. Esli ne
ukazan i pervyj parametr, ispol'zuetsya obrazec /\s+/.
Obratnaya funkciya -- join -- beret spisok znachenij i skleivaet ih,
vstavlyaya mezhdu nimi stroku-svyazku, peredannuyu ej v pervom parametre:
$s = join(":", @a);
Regulyarnye vyrazheniya yavlyayutsya, pozhaluj, samym moshchnym sredstvom Perl,
prednaznachennym dlya obrabotki tekstov, i v nashem kratkom izlozhenii my daleko
ne ischerpali vse ih vozmozhnosti.
Pakety, biblioteki, moduli, klassy i ob容kty
Pakety prednaznacheny dlya razdeleniya global'nogo prostranstva imen. Po
umolchaniyu vse programmy vypolnyayutsya v pakete main, poka direktiva package ne
vybiraet drugoj paket. Dlya dostupa k imenam, opisannym v drugom pakete,
ispol'zuetsya sintaksis $ImyaPaketa::ImyaPeremennoj.
Moduli predstavlyayut soboj otdel'nye fajly, soderzhashchie nabor
vzaimosvyazannyh funkcij. Kazhdyj modul' imeet vneshnij interfejs i, kak
pravilo, opisyvaet svoi global'nye peremennye i funkcii v otdel'nom pakete.
K osnovnoj programme moduli podklyuchayutsya s pomoshch'yu direktiv use i
require. Direktiva use podklyuchaet modul' na etape kompilyacii programmy (hotya
Perl formal'no i yavlyaetsya interpretiruemym yazykom, neposredstvenno pered
ispolneniem proishodit kompilyaciya ishodnyh tekstov programmy), direktiva
require zagruzhaet modul' vo vremya vypolneniya.
Formal'no v Perl net sredstv dlya sozdaniya sostavnyh tipov dannyh
napodobie struktur ili klassov v S++, no imeyushchihsya v nem sredstv vpolne
dostatochno dlya ih dovol'no blizkoj imitacii.
Obychnye struktury imitiruyutsya v Perl s pomoshch'yu anonimnyh heshej:
$record = {
NAME => 'record1',
FIELD1 => 'value1',
FIELD2 => 'value2',
FIELD3 => 'value3',
};
print $record->{FIELD1};
$records{$record->{NAME}} = $record;
$records{"record1"}->{FIELD1} = 1;
Klassy v Perl predstavlyayut soboj pakety, a ob容kty -- nechto (obychno vse
ta zhe ssylka na anonimnyj hesh), privedennoe s pomoshch'yu funkcii bless k
klassu.
Vnutri paketa obychno sushchestvuet funkciya-konstruktor, kotoraya vypolnyaet
vsyu etu rabotu. Tipichnyj konstruktor vyglyadit kak
sub new
{
my $class = shift; # poluchaem imya klassa
my $self = {}; # vydelyaem novyj hesh dlya ob容kta
bless($self, $class); # privodim hesh k klassu
$self->{FIELD1} = "value1";# inicializiruem polya ob容kta
$self->{FIELD2} = "value2";
return $self;
}
Esli dannyj konstruktor opisan v pakete Class, to ispol'zovat' ego
mozhno kak
use Class;
$object1 = Class::new("Class");
$object2 = Class->new();
$object3 = new Class;
Vse tri zapisi ekvivalentny.
V dal'nejshem pri vyzove funkcij, opisannyh v pakete Class, cherez
ob容kty, vozvrashchennye konstruktorom, v pervom parametre im budet
peredavat'sya ssylka na dannye ekzemplyara:
sub f
{
my $self = shift;
$self->{FIELD1} = shift;
}
Fakticheski, Perl-programmistu prihoditsya vruchnuyu delat' vse to, chto S++
ot nego skryvaet za izyashchnym sintaksisom.
Osnovnye biblioteki, ispol'zuemye v web-programmirovanii
Odni i te zhe zadachi web-programmirovaniya mogut reshat'sya na Perl
razlichnymi sposobami, vybor podhodyashchego dlya konkretnogo prilozheniya -- v
znachitel'noj stepeni delo vkusa. Glavnyj lozung Perl -- "Vsegda est' bol'she
odnogo resheniya" (There's more than one way to do it, TMTOWTDI). V prilozhenii
k materialu tekushchego razdela, odnu i tu zhe rabotu vy mozhete sdelat'
samostoyatel'no, vruchnuyu razbiraya stroki ili otsylaya pakety, a mozhete
doverit' ee standartnym bibliotekam, kotorye, vprochem, tozhe mozhno
ispol'zovat' po-raznomu. Professional'naya cherta programmistov -- len' -- kak
pravilo, tolkaet nas po vtoromu puti, no dobrosovestnost' i lyubopytstvo
prinuzhdayut posmotret', kak zhe eto vse ustroeno vnutri.
Servernye prilozheniya
Dlya nachala rassmotrim zadachu sozdaniya servernogo prilozheniya. Kak bylo
opisano vyshe, informaciya iz formy sobiraetsya v stroku vida
param1=value1¶m2=value2...¶mN=valueN, kotoraya popadaet v servernoe
prilozhenie libo cherez peremennuyu okruzheniya QUERY_STRING, libo cherez
standartnyj vvod, v poslednem sluchae peremennaya okruzheniya CONTENT_LENGTH
soderzhit ee razmer. Metod, kotorym peredavalis' dannyj, zadaetsya peremennoj
okruzheniya REQUEST_METHOD.
Dostup k peremennym okruzheniya v Perl osushchestvlyaetsya cherez associativnyj
massiv %ENV, dlya chteniya stroki zadannogo razmera iz vhodnogo potoka
predpochtitel'nej vospol'zovat'sya funkciej read. Vsya procedura polucheniya
vhodnoj stroki vyglyadit tak (v real'noj programme stoilo by dobavit'
ogranichenie na dlinu vhodnoj stroki):
if($ENV{"REQUEST_METHOD"} eq 'POST')
{
read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
}
else
{
$query = $ENV{'QUERY_STRING'};
}
Dalee nam ponadobitsya razbit' vhodnuyu stroku na sostavlyayushchie:
@params = split(/&/, $query);
Teper' @params soderzhit spisok stroki vida param1=value1. Dalee nam
pridetsya vydelit' iz nih imena i znacheniya, ne zabyvaya o neobhodimosti
dekodirovaniya nestandartnyh simvolov:
foreach $p(@params)
{
($name, $value) = split(/=/, $);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$in{$name} = $value;
}
Vpervye vstretivshayasya nam funkciya hex zanimaetsya preobrazovaniem
"shestnadcaterichnaya stroka->chislo", funkciya pack -- preobrazuet poluchennoe
znachenie v binarnuyu formu, osushchestvlyaya v nashem sluchae preobrazovanie "kod
simvola->simvol".
Po zavershenii cikla vse parametry formy okazyvayutsya razmeshchennymi v
associativnom massive %in, i ih znacheniya mozhno poluchit' kak $in{'param1'}.
Dalee sleduet soderzhatel'naya chast' nashej programmy, obrabotka vhodnyh
parametrov, vyborka dannyh iz baz i t.p. Nakonec, obrabotannuyu informaciyu
neobhodimo vernut' pol'zovatelyu. V pervuyu ochered' neobhodimo soobshchit'
klientu, kak imenno on dolzhen rassmatrivat' peredavaemuyu dalee informaciyu.
Kak my pomnim, eto osushchestvlyaetsya s pomoshch'yu HTTP-zagolovkov.
Kak pravilo, ispol'zuetsya dva sposoba -- perenapravlenie klienta na
novyj adres, ili formirovanie virtual'nogo dokumenta. V pervom sluchae vse,
chto ot nas trebuetsya -- vyvesti na standartnyj vyvod zagolovok Location:
print "Location: <u>http://newurl/text.html\n\n"</u>;
Vo vtorom sluchae my soobshchaem klientu, chto vsya posleduyushchaya informaciya
dolzhna rassmatrivat'sya, k primeru, kak html-fajl:
print "Content-type: text/html\n\n";
print '<html><head><title>Ok</title></head><body>Results:
<br>...</body></html>';
CHerez HTTP-zagolovki peredaetsya massa vspomogatel'noj informacii --
versiya servera, informaciya o kliente, cookie, sposob avtorizacii i t.p.
Kak vidite, nichego slozhnogo v poluchenii i peredache informacii
CGI-prilozheniem net, no dejstviya pri etom vypolnyayutsya tipovye, i voznikaet
estestvennoe zhelanie napisat' ih raz i navsegda i pomestit' v biblioteku. My
ne pervye, u kogo vozniklo takoe zhelanie, tak chto teper' vmesto perenosa iz
skripta v skript tipovogo koda mozhno vospol'zovat'sya standartnym (nachinaya s
versii Perl 5.004) modulem CGI.pm:
use CGI;
$Query = new CGI;
$val1 = $Query->param('param1'); # poluchaem znachenie parametra
$cookie1 = $Query->cookie('cookie1'); # poluchaem znachenie cookie
# Podgotavlivaem novyj cookie:
$newcookie = $Query->cookie(
-name=>'new', # imya
-value=>'value', # znachenie
-expires=>"+1y", # prekrashchaet dejstvie cherez god
-domain=>'www.mydomain.ru' # opredelen dlya nekotorogo domena
);
Formiruem i vyvodim HTTP-zagolovki:
print $Query->header(
-type=>'text/html',
-cookie=>$newcookie,
-Pragma=>"no-cache"
# ...
);
Takzhe CGI.pm soderzhit funkcii dlya formirovaniya html-koda, sohraneniya
rezul'tatov zaprosa v fajle i t.p. Dopolnitel'nuyu informaciyu o module mozhno
poluchit' s pomoshch'yu komandy perldoc CGI.
Klientskie prilozheniya
Napisanie klientskih web-prilozhenij na Perl stroitsya po obratnoj sheme
-- formiruem stroku parametrov i HTTP-zagolovki, soedinyaemsya s serverom,
peredaem emu zapros i ozhidaem otvet. Kak obychno, prodelat' eto mozhno
neskol'kimi sposobami.
1. Recept dlya lyubitelej ruchnoj raboty. Ispol'zuem nizkourovnevye
funkcii dlya raboty s soketami, yavlyayushchiesya minimal'nymi obertkami vokrug
sootvetstvuyushchih funkcij na S.
use Socket;
# podgotavlivaem strochku s parametrami formy
$forminfo = 'param1=val1¶m2=val2';
# podgotavlivaem i osushchestvlyaem soedinenie:
# vybiraem rabotu cherez TCP
$proto = getprotobyname('tcp');
# otkryvaem potokovyj soket
socket(Socket_Handle, PF_INET, SOCK_STREAM, $proto);
# podgotavlivaem informaciyu o servere
$port = 80;
$host = "www.somehost.com";
$sin = sockaddr_in($port,inet_aton($host));
# soedinyaemsya s serverom
connect(Socket_Handle,$sin) || die ("Cannot connect");
# peredaem serveru komandy, ispol'zuya deskriptor soketa
# sobstvenno komanda GET
send Socket_Handle,"GET /cgi-bin/env.cgi?$forminfo HTTP/1.0\n",0;
# HTTP-zagolovki
send Socket_Handle,"User-Agent: my agent\n",0;
send Socket_Handle,"SomeHeader: my header\n",0;
send Socket_Handle,"\n",0;
# nachinaem chtenie iz deskriptora soketa analogichno
# tomu, kak chitali iz fajla.
while (<Socket_Handle>)
{
print $_;
}
close (Socket_Handle);
Pri ispol'zovanii nestandartnyh simvolov v parametrah formy ih sleduet
preobrazovat' v vid %XX, gde XX -- ih shestnadcaterichnoe predstavlenie.
Kodirovanie vypolnyaetsya sleduyushchim kodom:
$value=~s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg;
2. CHut' men'she ruchnoj raboty -- ispol'zovanie modulya IO::Socket.
Rassmotrim ego na primere metoda POST:
use IO::Socket;
$forminfo = 'param1=val1¶m2=val2';
$host = "www.somehost.com";
$socket = IO::Socket::INET->new(Proto => "tcp",
PeerAddr => $host,
PeerPort => "http(80)")
or die ("Cannot connect");
$socket->autoflush(1);
$length = length($forminfo)+1;
$submit = "POST $path HTTP/1.1\n".
"Content-type: application/x-www-form-urlencoded\n".
"Content-length: $length\n".
"Host: $host\n\n"
"$forminfo\n";
print $socket $submit;
while(<$socket>)
{
print;
}
close $remote;
3. Nakonec, naibolee komfortnyj dlya programmista variant --
ispol'zovanie kompleksa modulej libwww-perl, ili LWP. LWP, kak pravilo,
vhodit vo vse poslednie distributivy Perl, krome togo, poslednyaya versiya
vsegda dostupna na CPAN i na <u>http://www.linpro.no/lwp/.</u>
Osnovnye moduli, ispol'zuemye pri rabote s LWP (dlya polucheniya
dopolnitel'noj infomracii o kazhdom module vospol'zujtes' komandoj perldoc
<imya modulya>):
LWP::UserAgent
LWP::Simple
HTTP::Request
HTTP::Response
HTTP::Headers
HTTP::Cookies
LWP::Simple prednaznachen dlya prostejshih operacij napodobie polucheniya
informacii o dokumente ili poluchenii dokumenta metodom GET:
use LWP::Simple;
$content = get('http://somehost/text.html');
LWP::UserAgent -- osnovnoj modul' dlya bolee tonkoj raboty s web. Ego
naznachenie -- sozdanie virtual'nogo brouzera, vypolnyayushchego vsyu rabotu po
vzaimodejstviyu s serverom:
# sozdanie
$UserAgent = new LWP::UserAgent;
# zadanie stroki s imenem "brouzera"
$UserAgent->agent("MoZilla 9.0 (non-compatible; MSIE 9.3; PalmOS)");
# rabota cherez proksi
$UserAgent->proxy('http', $proxy);
HTTP::Request otvechaet za formirovanie zaprosa serveru, HTTP::Headers
-- za formirovanie zagolovkov zaprosa:
# formiruem zagolovki
$Headers = new HTTP::Headers(Referer => $referer);
# formiruem zapros
$Request = new HTTP::Request(POST => $url, $Headers);
# govorim, chto peredavat'sya budut dannye formy
$Request->content_type('application/x-www-form-urlencoded');
# peredaem dannye
$Request ->content($forminfo);
Vzaimodejstvie s serverom osushchestvlyaetsya funkciej request, vozvrashchayushchej
ob容kt HTTP::Response:
$Response = $UserAgent->request($Request);
if($Response->is_success) # uspeshno vypolnennyj zapros
{
# poluchaem informaciyu, vozvrashchennuyu serverom
$text = $Response->content;
}
Dlya raboty s cookie ispol'zuetsya modul' HTTP::Cookie i funkciya
cookie_jar, soobshchayushchaya nashemu virtual'nomu brouzeru o neobhodimosti
ispol'zovat' ob容kt Cookie:
my $SookieJar = new HTTP::Cookies;
$UserAgent->cookie_jar($CookieJar);
Dlya sohraneniya i zagruzki cookie ispol'zuyutsya funkcii
$CookieJar->load($cookiefilename);
$CookieJar->save($cookiefilename);
Mozhno formirovat' ih znacheniya i vruchnuyu s pomoshch'yu funkcii set_cookie.
Dlya dostupa k resursam, zashchishchennym sredstvami servera, ispol'zuetsya
HTTP-zagolovok Authorization. Ego znachenie dolzhno soderzhat' tip avtorizacii
(obychno BASIC) i stroku vida "imya_pol'zovatelya:parol'", v sluchae
basic-avtorizacii zakodirovannuyu base64. Dlya kodirovaniya mozhno
vospol'zovat'sya modulem MIME::Base64:
use MIME::Base64;
$authorization = MIME::Base64::encode_base64("$name:$password");
$Request->header(Authorization => "BASIC $authorization");
Rabota s bazami dannyh
Dlya raboty s bazami dannyh v Perl ispol'zuetsya standartnyj interfejs
programmirovaniya DBI, obespechivayushchij dostup k bol'shinstvu sushchestvuyushchih SUBD
s pomoshch'yu podklyuchaemyh drajverov. Shemy podklyucheniya k razlichnym SUBD
(tochnee, pravila formirovaniya imeni istochnika dannyh) mogut neznachitel'no
razlichat'sya, my rassmotrim rabotu s ispol'zovaniem mySQL.
V pervuyu ochered' neobhodimo podklyuchit' modul' DBI:
use DBI;
Dalee podklyuchaemsya k baze dannyh:
my $dbh = DBI->connect('DBI:mysql:hostname:base:port', 'user,
'password, { RaiseError => 1, AutoCommit => 1});
Zdes' $dbh -- deskriptor bazy dannyh, ispol'zuemyj v dal'nejshej rabote,
DBI:mysql:hostname:base:port -- imya istochnika dannyh, vklyuchayushchee imya
drajvera, imya hosta, bazy, k kotoroj my podklyuchaemsya, i nomer porta, na
kotoryj nastroen sql-server, user/password -- imya i parol' pol'zovatelya,
imeyushchego dostup k baze, v poslednem parametre peredayutsya razlichnye flagi.
Po zavershenii raboty zhelatel'no zakryt' deskriptor:
$dbh->disconnect();
Vozmozhno ispol'zovanie dvuh sposobov raboty s bazoj. V sluchae, esli nam
nuzhno tol'ko peredat' informaciyu v bazu, ispol'zuetsya metod do, parametrom
kotorogo yavlyaetsya stroka SQL-zaprosa:
$dbh->do("insert into mytable values (1,1)");
Esli zhe neobhodimo poluchit' informaciyu iz bazy, ispol'zuetsya sleduyushchaya
procedura:
1. Poluchaem deskriptor komandy s pomoshch'yu metoda prepare:
my $sth = $dbh->prepare ("select * from mytable where field1>1");
2. Vypolnyaem komandu:
$sth->execute();
3. Poluchaem dannye. Ispol'zuetsya odin iz chetyreh metodov:
fetchrow_array
fetchrow_hash
fetchrow_arrayref
fetchrow_hashref
Metody vozvrashchayut sootvetstvenno massiv, hesh, ssylku na massiv, ssylku
na hesh, v kotoryh hranyatsya znacheniya polej tekushchej zapisi. Dlya vyborki vseh
zapisej ispol'zuetsya cikl, posle vyborki vseh zapisej funkcii vozvrashchayut
pustoj spisok, vosprinimaemyj kak znachenie false:
while(my $hash_ref = $sth->fetchrow_hashref)
{
foreach my $fieldname(keys %$hash_ref)
{
print "$fieldname: $hash_ref->{$fieldname }\n";
}
print "\n";
}
4. Osvobozhdaem resursy:
$sth->finish();
Pri peredache tekstovoj informacii v bazu rekomenduetsya predvaritel'no
obrabotat' ee metodom $dbh->quote(), rasstavlyayushchim kavychki i upravlyayushchie
simvoly v stroke v sootvetstvii s pravilami ispol'zuemoj SUBD.
Krome togo, vozmozhno ispol'zovanie privyazki parametrov v vide:
$sth = $dbh->prepare("select * from mytable where field1=?");
$sth->bind_param(1, "znachenie parametra");
$sth->execute();
libo
$sth = $dbh->prepare("select * from mytable where field1=?");
$sth->execute("znachenie parametra");
V etom sluchae v metode quote neobhodimosti net, on vyzyvaetsya
avtomaticheski.
Ispol'zovanie privyazki parametrov osobenno effektivno pri vypolnenii
neskol'kih odnotipnyh zaprosov podryad. V etom sluchae dostatochno odin raz
podgotovit' zapros s pomoshch'yu funkcii prepare, i vypolnyat' ego s pomoshch'yu
funkcii execute stol'ko raz, skol'ko neobhodimo.
Zadaniya dlya laboratornyh rabot
1. Prostejshaya kartoteka
Cel' raboty.
Osvoenie bazovyh vozmozhnostej yazyka Perl, raboty so strukturami dannyh,
fajlovym vvodom-vyvodom.
Postanovka zadachi.
Realizovat' na Perl konsol'noe prilozhenie, pozvolyayushchee dobavlyat',
redaktirovat', vyvodit' na ekran, sohranyat' v fajl spisok odnotipnyh
ob容ktov (studentov gruppy, sluzhashchih firmy, zhitelej doma i t.p.), kazhdyj iz
kotoryh obladaet neskol'kimi atributami (imya, familiya, vozrast i t.p.).
Trebovaniya k realizacii.
ispol'zovat' direktivu use strict;
vzaimodejstvie s pol'zovatelem osushchestvlyaetsya cherez prostoe tekstovoe
menyu, vybor dejstviya -- vvod cifry;
menyu vklyuchaet v sebya sleduyushchie punkty: dobavit', redaktirovat', udalit'
ob容kt, vyvesti na ekran ves' spisok, sohranit' v fajl, zagruzit' iz fajla;
celesoobrazno realizovat' obrabotku menyu s pomoshch'yu hesha ssylok na
funkcii;
dannye sohranyayutsya v dbm-fajl;
pri zagruzke v pamyat' kazhdyj ob容kt hranitsya v vide ssylki na anonimnyj
hesh, vsya kartoteka hranitsya v vide massiva (libo hesha) ssylok.
2. Kartoteka s web-interfejsom
Cel' raboty.
Osvoenie sposobov postroeniya CGI-prilozhenij na Perl.
Postanovka zadachi.
Preobrazovat' konsol'noe prilozhenie kartoteki v CGI-prilozhenie,
rabotayushchee sovmestno s web-serverom.
Trebovaniya k realizacii.
dlya polucheniya informacii ot klienta ispol'zovat' standartnuyu biblioteku
CGI.pm;
sohranit' funkcii raboty s fajlami i shemu obrabotki menyu,
realizovannye v pervoj laboratornoj rabote, pri vyvode tekstovoj informacii
osushchestvlyat' preobrazovanie kodirovki cp866->win1251.
3. Kartoteka s web-interfejsom, ispol'zuyushchaya mySQL
Cel' raboty.
Osvoenie sposobov vzaimodejstviya Perl-prilozhenij s bazami dannyh.
Postanovka zadachi.
Preobrazovat' CGI-prilozhenie kartoteki, osnovannoe na rabote s
dbm-fajlami, v klienta bazy dannyh mySQL.
Trebovaniya k realizacii.
predusmotret' vozmozhnost' konvertirovaniya informacii, hranyashchejsya v
dbm-fajlah, v format mySQL;
ispol'zovat' mehanizm privyazki parametrov;
dobavit' ob容kt, obladayushchij rasshirennymi atributami (upravlyayushchij,
starosta i t.p.).
4. Klientskoe prilozhenie kartoteki
Cel' raboty.
Osvoenie tehniki postroeniya klientskih prilozhenij, ispol'zuyushchih
protokol http.
Postanovka zadachi.
Realizovat' na Perl konsol'noe klientskoe prilozhenie k kartoteke,
schityvayushchee iz dbm-fajla informaciyu ob ob容ktah, i peredayushchee ee
CGI-prilozheniyu iz tret'ej laboratornoj raboty po protokolu http dlya
zaneseniya v bazu.
Trebovaniya k realizacii.
ispol'zovat' biblioteku LWP;
pri peredache strokovoj informacii kodirovat' nestandartnye simvoly v
format %XX, gde XX -- shestnadcaterichnoe predstavlenie dannogo simvola, a
takzhe osushchestvlyat' preobrazovanie kodirovki cp866->win1251.
Rekomenduemaya literatura
Dekart A., Bans T. Programmirovanie na Perl DBI/Per. s angl. -- SPb:
Simvol-Plyus, 2000. -- 400 s.
Kristiansen T., Torkington N. Perl. Biblioteka programmista/Per s angl.
-- SPb.: "Piter", 2000. -- 736 s.
Najk D. Standarty i protokoly Interneta/Per. s angl. -- M.:
Izdatel'skij otdel "Russkaya redakciya" TOO "Channel Trading Ltd.", 1999, --
384 s.
Spejnaur S., Kuersia V. Spravochnik Web-mastera/Per. s angl. -- K.:
Izdatel'skaya gruppa BHV, 1997. -- 368 s.
SHvarc R., Kristiansen T. Izuchaem Perl/Per. s angl. -- K.: Izdatel'skaya
gruppa BHV, 1998. -- 320 s.