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&param2=value2...&paramN=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&param2=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&param2=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.