Dezvoltarea de Aplicatii Web Folosind Limbajul de Program Are Java
Program Are Perl
Transcript of Program Are Perl
-
7/22/2019 Program Are Perl
1/70
Sabin Corneliu Buraga
ntroducere nProgramare Perl
2005
-
7/22/2019 Program Are Perl
2/70
2
n loc de prefa
Acest material realizeazo prezentare generala limbajului de programare Perl, insis-
tnd asupra realizrii de script-uri Perl n contextul programrii Web pe partea de server
via paradigma CGI (Common Gateway Interface). De asemenea, se prezinto serie de exem-
ple de programe Perl i diverse propuneri de proiecte pentru a fi implementate de cititor.
Lucrarea de fase bazeaz, n cea mai mare msur, pe cartea S. Buraga et al., Progra-
mare Web n bash i Perl (include i un CD), Editura Polirom, Iai, 2002:
http://www.infoiasi.ro/~cgi/ .
Pentru aprofundarea limbajului Perl, cititorul este ncurajat sconsulte resursele bibli-
ografice. Mai mult, poate vizita situl autorului: http://www.infoiasi.ro/~busaco/ . A-teptm reacii i opinii la adresa e-mail [email protected] .
-
7/22/2019 Program Are Perl
3/70
3
1. Prezentare generala limbajului Perl
Pentru nceput, vom enumera cteva dintre caracteristicile specifice limbajului Perl.
1.1 Generaliti
Creat iniial pentru prelucrarea sofisticata informaiilor textuale, Perl(Practical Ex-
traction and Report Language) l are ca printe pe Larry Wall, n decursul timpului la
dezvoltarea limbajului contribuindi al
i numero
i programatori. Distribuit gratuit, Perl a
devenit favoritul administratorilor de sistem i al programatorilor de aplicaii Web, ns
poate fi utilizat asemeni altui limbaj general. Ca i Linux, Perl a crescut n mediul prielnic
al Internetului, varianta curenta limbajului fiind 5. Pe data de 18 decembrie 2005 se m-
plinesc 18 ani de la apariia limbajului. n curs de dezvoltare este versiunea Perl 6 a limba-
jului.
Iniial, limbajul a fost conceput special pentru mediile UNIX, mprumutnd o serie de
faciliti oferite de shell-urile i utilitarele standard i pstrnd filosofia de baza UNIX-
ului, dar n prezent Perl este disponibil pentru toate platformele actuale (e.g. Mac OS,
Windows sau OS/2).
n proiectarea limbajului s-au avut n vedere urmtoarele principii:
lucrurile simple sse poatrealiza uor, iar cele complexe snu fie impo-sibil de implementat;
existmai multe modaliti de realizare a unui program, n funcie de gra-dul de cunoatere a limbajului de ctre dezvoltatorul acelui program.
Drept caracteristici importante ale limbajului se pot enumera: modularitatea
Perl ofersuport pentru mai multe paradigme de programare, ca de exemplu cea
procedurali cea orientat-obiect; limbajul poate fi extins prin intermediul aa-
numitelor module, punndu-se la dispoziie un numr impresionant de module
standard;
portabilitateaProgramele Perl se pot executa frmodificri pe orice platform;
-
7/22/2019 Program Are Perl
4/70
4
expresivitatea i putereaLimbajul dispune de mecanisme puternice pentru manipularea datelor, prin in-
termediul expresiilor regulate i a tablourilor; de asemenea, Perl poate fi folosit ca
limbaj de sistem pentru lucrul cu entiti ale sistemului de operare (fiiere, dispo-zitive, procese, socket-uri);
viteza de dezvoltare a aplicaiilorCiclul compilare-execuie-depanare se poate realiza i itera rapid; Perl nu oferun
interpretor clasic, ci un compilator-interpretor.
Fiind gratuit i posednd numeroase mijloace de documentare online, Perl poate fi folo-
sit n special pentru dezvoltarea rapidde aplicaii de administrare a sistemului de operare
i destinate Web-ului, reprezentnd un mediu ideal pentru conceperea script-urilor CGI.Mai mult, anumite servere Web (e.g., Apache) includ interpretoare Perl interne.
1.2 Disponibilitate i documentaii
Mediul Perl se poate obine de pe Internet, via FTP sau HTTP, prin intermediul locai-
ilor CPAN (Comprehensive Perl Archive Network). Principala surs este
ftp://ftp.funet.fi , dar se pot folosi i alte locaii, listate la
http://www.perl.com/CPAN/ .
De asemenea, orice distribuie actual de Linux include interpretorul i manualele
standard Perl. Pentru Windows, platforma Perl cea mai popularesteActivePerl, disponi-
bili pe CD-ul volumului S. Buraga et al., Programare Web n bash i Perl, Polirom, Iai,
2002: http://www.infoiasi.ro/~cgi/ .
Pentru a genera codul executabil al interpretorului Perl din sursele preluate din Inter-
net, pentru un mediu UNIX (Linux) va trebui sscriem urmtoarele linii de comenzi de
laprompt-ul sistemului, ca utilizatori cu drepturi de root:
(infoiasi)$ ./configure # pentru configurare automata(infoiasi)$ ./Configure # pentru configurare manuala
(infoiasi)$ make
(infoiasi)$ make test
(infoiasi)$ make install
Perl include o serie de documentaii onlinecare pot fi parcurse prin intermediul bine-
cunoscutei comenzi man (ncercai, de exemplu, man perl). Pentru anumite detalii sau
documentaii referitoare la modulele Perl, se poate folosi comanda perldoc. Astfel, dac
dorim s aflm amnunte despre funcia standard Perl printf vom da perldoc
printf. De asemenea, putem recurge la opiunea -fpentru a afla detalii despre o funcie(e.g.perldoc -f connect).
-
7/22/2019 Program Are Perl
5/70
5
Paginile de manual cele mai importante sunt:
perl- o trecere n revista documentaiilor Perl; perlfaq - rspunsuri la ntrebrile puse frecvent despre Perl (Frequently
Asked Questions - FAQ);
perlsyn - sintaxa limbajului (vezi i perlrun - execuiascript-urilor Perl, perldebug- depanarea programelor, perlstyle- ghid de stil,
perlfunc- funcii predefinite, perlsub- subrutinele Perl);
perldata - structurile de date Perl (vezi i perlre - expresii regulate,perldsc- introducere n structuri de date, perllol- liste de liste, perlref- re-
ferine, perlvar- variabile predefinite);
perlop- operatorii i precedena lor; perlmod- modulele Perl (vezi i perlmodlib); perlobj - suport pentru programarea obiectual (vezi i
perltool - tutorial privind programarea orientat-obiect,
perlbot- exemple de obiecte).
Pentru a avea acces la una dintre documentaiile dorite, este suficient s tastm, de
exemplu, man perlsyn.
Versiunile mai vechi de Perl puneau la dispoziie documentaia n format text (Plain
Old Documentation - POD). Pentru amnunte, consultai man pod, iar pentru a o converti
n alte formate se pot folosi comenzile pod2man, pod2htmlsau pod2text.
De asemenea, cititorii interesai pot parcurge articolele postate pe grupurile de tiri
comp.lang.perl sau documentaiile n format hipertext de la
http://www.perl.com/perl/ .
1.3 Trecere n revista limbajului
Spre deosebire de alte limbaje, Perl este un limbaj interpretat, n sensul cinstruciunile
Perl nu sunt convertite n cod executabil (nu se genereazun fiier executabil, spre a fi
rulat independent de interpretorul Perl). Vom spune despre programele Perl c sunt
script-uri, un limbaj de tip scriptfiind destinat sprelucreze, sautomatizeze i sintegreze
facilitile oferite de un anumit sistem (e.g., sistem de operare, server Web, navigator Web,
aplicaie de birou). Alte limbaje de tip scriptsunt bash, Python, Tcl/TkoriJavaScript.
Perl nu pune la dispoziie un interpretor clasic, n sensul cun scriptPerl nu este inter-
pretat linie cu linie, ci n prealabil va fi compilat complet, de o componentnumitmotor(engine) Perl, rezultnd un limbaj intermediar, realizndu-se diverse optimizri i
-
7/22/2019 Program Are Perl
6/70
6
raportndu-se posibililele erori/avertismente sintactice sau semantice. Acest cod inter-
mediar, n cazul n care nu apar erori, va fi dat spre execuie interpretorului Perl.
Modalitatea de execuie a unui scriptPerl
Avnd n vedere cPerl este un interpretor (similar shell-ului bash), prima linie a unui
fiier sursPerl va trebui sfie urmtoarea:
#!/usr/bin/perl
Aceastlinie indicncrctorului sistemului de operare locaia interpretorului Perl (s-
ar putea n unele cazuri sdifere de directorul /usr/bin, dai whereis perlpentru a
vedea unde a fost instalat). Ea va fi ignoratn alte medii diferite de UNIX (Linux), fiind
consideratsimplu comentariu.
Pentru a putea fi executat, fiierul memornd script-ul Perl va trebui saibpermisiunea
de execuie setatprin comanda chmod.
Un prim program Perl
n continuare, vom scrie un program Perl din care vom putea remarca principalele ca-
racteristici definitorii ale limbajului. Ne propunem sconcepem un scriptcare scontori-
zeze numrul de apariii ale elementelor dintr-un document XML:
#!/usr/bin/perl
# elemente_xml.pl
# program care furnizeaza lista elementelor unice
# prezente intr-un document XML si
# numarul de aparitii ale fiecaruia
my %elemente, %aparitii;
# programul principal
while () {# cit timp se mai poate citi de la intrarea standard...
-
7/22/2019 Program Are Perl
7/70
7
if (/]*>/) {
# am intilnit "" urmate de ">"
# apelam o rutina de extragere a unui element
&extragere_element;}
}
# am terminat de prelucrat
# vom afisa lista elementelor gasite
&afiseaza_elemente();
# gata!
exit;
# subrutina de afisare a elementelor gasite
# se vor sorta cheile tabloului asociativ %elemente# si se va afisa la iesirea standard fiecare cheie
sub afiseaza_elemente {
# pentru fiecare element al tabloului...
foreach $element (sort keys %elemente) {
# afisam formatate numele de element si
# numarul aparitiilor lui
printf "%-20s - %2d aparitii.\n",
"'$elemente{$element}'", $aparitii{$element};
}
}
# subrutina de extragere a numelor de elemente
# apelata de fiecare data cind un element este detectat
# intr-o linie citita de la intrarea standard
# aceste nume vor fi stocate intr-un tablou asociativ
# pentru extragerea numelor de elemente se va folosi
# o expresie regulata =~ si variabilele $' si $&
sub extragere_element {
$restul_liniei = $_;# atita timp cit in linia transmisa mai sunt
# alte elemente XML...
while ($restul_liniei =~ /]*>/) {
$restul_liniei = $';
$element = $&;
# orice caracter majuscul e transformat in minuscul
$element =~ tr/A-Z/a-z/;
# orice "" este eliminat
$element =~ s/()//g;
# trecem la urmatoarea iteratie# daca elementul e instructiune de procesare
-
7/22/2019 Program Are Perl
8/70
8
next if /^(
-
7/22/2019 Program Are Perl
9/70
9
Rezultatul afiat la ieirea standard va fi:
'an' - 3 aparitii.
'nume' - 3 aparitii.
'student' - 3 aparitii.
'studenti' - 1 aparitii.
Interpretorul Perl poate fi rulat cu diverse opiuni, de exemplu opiunea -wcare va afi-
a toate avertismentele n timpul compilrii i rulrii codului intermediar. De multe ori,
aceastopiune va fi utilizatdin raiuni de verificare a corectitudinii programului. Desi-
gur, pot fi date i alte opiuni, pentru mai multe detalii cititorul fiind ndemnat sconsulte
man perl. Aceste opiuni pot fi transmise interpretorului i n cadrul liniei de preambul
al codului, de exemplu:
#!/usr/bin/perl -w -t
O opiune utileste "-e" care ne permite sexecutm linii de cod Perl direct din linia
de comenzi:
(infoiasi)$ perl -e 'print "Salut!"'
Astfel, putem folosi aceastopiune pentru a afla versiunea curenta limbajului, recur-
gnd la afiarea valorii variabilei predefinite $]:
(infoiasi)$ perl -e 'print "$]\n";'
5.006
De asemenea, utiliznd opiunea -vputem afla versiunea curenta distribuiei Perl in-
stalate n sistem:
(infoiasi)$ perl -v
This is perl, v5.6.0 built for i386-linux
-
7/22/2019 Program Are Perl
10/70
10
Caracteristici principale
Putem observa cprogramul de mai sus este foarte asemntor cu un program scris nlimbajul C sau cu un scriptbash.
n cele ce urmeazvom ncerca sdescriem caracteristicile principale ale limbajului:
sintaxa- limbajul Perl are o sintaxinspiratdin C, delimitatorii fiind spa-iile albe. Dup cum era de ateptat, Perl este case sensitive, iar comentariile sunt
precedate de caracterul "#". Fiecare instruciune a limbajului este terminat de
";", iar parantezele acolade sunt delimitatori de bloc de instruciuni. Recoman-
dm indentarea construciilor sintactice Perl i utilizarea ct mai multor comenta-rii pentru ca programele spoatfi uor de parcurs i de neles de ctre cititor.
tipuri de date i variabile - prima linie a programului declar dou tablouriasociative care vor stoca elementele gsite i respectiv numrul de apariii ale
acestora:
my %elemente, %aparitii;
Reamintim faptul co variabilreprezinto zon(de obicei, contigu) de me-
morie n care se stocheazo valoare de un anumit tip, zonei fiindu-i asociat un
nume (identificator al acelei variabile). Aceastzonpoate fi publicsau privat,permanentsau temporarpe parcursul execuiei unui program. Numele unei va-
riabile trebuie snceapcu o literi poate conine caracterele alfa-numerice i
"_".
Tipurile de date n Perl sunt fie scalare (simple) sau compuse (complexe).
Ca tipuri scalarese pot aminti ntregii cu semn i numerele flotante (dublpreci-
zie). Tot drept tip scalar se considertipul desemnnd iruri de caractere. Fiind
un limbaj interpretat, Perl nu impune declararea variabilelor, ele fiind automat ini-
ializate, n funcie de contextul utilizrii. Implicit, se considerco variabilnu-
mericeste iniializatcu 0, iar un ir de caractere cu valoarea ""(ir vid). irurile
de caractere sunt delimitate de apostrofuri sau de ghilimele. Ca i n C, putem fo-
losi aa-numitele caractere escape, ca de exemplu "\n" (linie nou) sau "\t" (carac-
terul tab). Pentru a avea acces la valoarea unei variabile scalare, vom prefixa nu-
mele ei cu caracterul "$" dupcum se poate remarca din exemplul de mai jos:
$nr_studenti++;
$pi = 3.14152965;
$limbaj = "Perl";
-
7/22/2019 Program Are Perl
11/70
11
n loc de a folosi ghilimele sau apostrofuri, irurile pot fi delimitate de con-
strucii precum:
q/Victor Tarhon-Onu/ # identic cu 'Victor Tarhon-Onu'
qq/Victor Tarhon-Onu/ # identic cu "Victor Tarhon-Onu"# executia unei comenzi, identic cu `ls -la`
qx/ls -la/
qw/Perl C Java/ # lista de cuvinte
Ca i la shell-ul bash, diferena dintre apostrofuri i ghilimele ca delimitatori de
ir este datde faptul cvaloarea variabilelor este accesibiln cazul ghilimelelor:
print "Studenti: $nr_studenti\n";
# variabila $limbaj nu va fi expandata
print 'Acest $limbaj este greu?';
Drept tipuri complexeavem la dispoziie:
tablourile indexatesunt liste ordonate de scalari, elementele unei listefiind accesibile prin intermediul unui indice numeric; numele unui vector
va fi precedat de caracterul "@", iar indicele va porni de la zero i va fi n-
cadrat ntre paranteze ptrate:
@absenti[$nr_studenti] = 20;
@limbaje = ("Ada", "C", "Java", "Lisp", "Perl");
@mix = ("Pink", 1978, "Floyd", $pi);
Dupcum se poate remarca, un tablou poate conine elemente etero-
gene, de tipuri scalare diferite. Elementele delimitate de "("
i ")" compun o list. Accesarea unui element se va realiza astfel (caracte-
rul "@" este nlocuit cu "$" pentru cselectm un element scalar):
$limbaje[4]
De asemenea, putem avea acces la un sub-tablou indicnd un interval
de indici (sub-tabloul fiind tot un tablou va avea numele prefixat de "@"):
print "Primele trei limbaje: @limbaje[0..2]\n";
Pentru a aduga i elemente la sfritul unui tablou, vom putea uzita de
funciile predefinite push()i pop(), respectiv:
push(@limbaje, "Prolog");
print "Ultimul limbaj eliminat:", pop(@limbaje);
Dac dorim s adugm i s tergem elemente la i de la nceputul
unui tablou, vom utiliza unshift()i shift(), respectiv.
-
7/22/2019 Program Are Perl
12/70
12
Lungimea unui tablou va putea fi aflat astfel (cele trei construcii au
acelai efect):
$nr_limbaje = @limbaje;
$nr_limbaje = scalar(@limbaje);
Pentru ca elementele unui tablou sdevincuvinte ale unui ir de ca-
ractere, vom utiliza o construcie de genul:
$sir = "@limbaje";
Implicit, elementele tabloului vor fi delimitate de un spaiu. Pentru a
schimba delimitatorul, vom apela la variabila scalarpredefinitcu nume-
le "@"" dupcum se observn urmtorul exemplu:
$" = "|";$sir = "@limbaje";
print $sir, "\n";
Tablourile pot fi utilizate nu doar n partea dreapta unei atribuiri, ci i
n partea stng:
($primul, $al_doilea) = @limbaje;
($primul, @restul) = @limbaje;
Pentru prima linie, variabila $primava primi valoarea primului element
al tabloului @limbaje, iar $al_doileavaloarea celui de-al doilea elemental aceluiai tablou. n a doua linie, $primava primi de asemenea valoarea
primului element al tabloului, dar @restulva fi un tablou coninnd res-
tul elementul tabloului @limbaje.
Folosind o construcie similarputem realiza atribuiri multiple de vari-
abile scalare ntr-o singurlinie de program:
($studenti, $profesori) = ($absenti, 7);
Aceasta are acelai efect ca atribuirile individuale:
$studenti = $absenti;
$profesori = 7;
tablourile asociative(hash) sunt tablouri n care indicele numeric estesubstituit de un ir de caractere. Le putem vedea ca perechi (cheie, valoa-
re), cheile sau valorile nefiind ordonate. Tablourile asociative vor fi acce-
sate precednd numele lor cu caracterul "%", putndu-le iniializa astfel:
# numarul de studenti din fiecare grupa
%grupe = ("grupa1", 25,
"grupa2", 20,
-
7/22/2019 Program Are Perl
13/70
13
"grupa3", 24,
"grupa4", 25);
O modalitate mai intuitiveste:
%grupe = ("grupa1" => 25,
"grupa2" => 20,
"grupa3" => 24,
"grupa4" => 25);
Pentru a accesa un anumit element, vom putea scrie:
print "Grupa a 3-a are $grupe{"grupa3"} studenti.\n";
ntre acolade vor putea fi precizate numai nume de chei, nu valori ale
cheilor, iar cheile nu pot fi accesate specificnd valorile lor ntre acolade.
O cheie trebuie sfie unic, dar valorile cheilor pot fi duplicate.
Conversia din tabel indexat n tabel asociativ i invers se poate realiza
tot prin intermediul atribuirii obinuite.
Asupra unui tablou asociativ nu mai putea aplica funciile push(),
pop(), shift() sau unshift(), dar putem folosi funciile keys() i
values()pentru a obine lista cheilor i respectiv cea a valorilor unui ta-
blou asociativ. Aceste liste pot fi iterate cu ajutorul instruciunii foreach.
Funcia standard each()returneazo pereche cheie-valoare putnd fi fo-
lositde asemenea la parcurgerea unui tablou asociativ:
while (($grupa, $studenti) = each(%grupe)) {
print "Grupa $grupa are $studenti studenti.\n";
}
Inserarea se poate face simplu prin:
$grupe{"grupa5"} = 20;
Un element se poate elimina cu ajutorul funciei delete(), iar existen-
a unui element se poate afla prin exists():
if exists($grupe{"grupa4"}) {
delete($grupe{"grupe4"});
}
Pentru sortarea unui tablou, vom apela funcia sort(). Aceastfuncie
permite precizarea unei funcii de comparaie a elementelor definit de
utilizator. Inversarea unei liste de elemente se va realiza cu reverse().
-
7/22/2019 Program Are Perl
14/70
14
Remarci
Din moment ce numele de variabile sunt prefixate de caractere di-ferite n funcie de tipul variabilelor, putem folosi n acelai program nu-me de variabile precum %studenti, $studentii @studenti fram-
biguiti. Pentru a evita conflictul cu nume de variabile sau de funcii
predefinite (care ntotdeauna sunt scrise cu minuscule), vom putea alege
identificatori de variabile scrii cu majuscule:
# se evita conflictul cu numele de functie log()
open(LOG, 'httpd.log');
Sunt puse la dispoziie diverse variabile predefinite, utile n anumi-te contexte. Se pot meniona, de exemplu, variabilele:
$$- identificatorul procesului curent; $?- codul de eroare returnat de ultima comandexecuta-
t;
$0- numele programului care se execut; $]- versiunea interpretorului Perl, ca numr zecimal (e.g.
5.006);
$@ - mesajul de eroare semnalat de interpretorul Perl re-turnat n urma execuiei celei mai recente funcii eval();
$,- separatorul de ieire folosit de print()pentru afia-rea cmpurilor de date;
$\- separatorul de ieire pentru afiarea nregistrrilor; $"- separatorul utilizat la afiarea listelor; $_ - intrarea implicit sau spaiul de cutare ntr-un ir
(poate fi folositi $ARG).
De asemenea, sunt disponibile urmtoarele tablouri:
@ARGV- argumentele furnizate scriptului ($ARGV[0]referprimul argument, nu numele programului);
%ENV- variabilele de mediu disponibile; @INC- lista locaiilor bibliotecilor standard Perl, utilizate la
includere.
-
7/22/2019 Program Are Perl
15/70
15
Desigur, putem combina valorile scalare cu tablourile indexate sauasociative, genernd structuri de date deosebit de complexe (tablouri aso-
ciative coninnd ca elemente alte tablouri indexate sau asociative, liste de
liste etc.). Pentru amnunte, se poate consulta man perllol. n afara tipurilor prezentate, mai pot fi utilizate referinele la sub-
rutine (funcii sau proceduri), prefixate de caracterul "&" sau la alte obiec-
te.
Putem crea o referinla orice variabila sau subrutinPerl, prin prefixa-
rea acelui identificator cu caracterul "\":
$referinta_la_mediu = \%ENV;
$referinta_la_rutina = \&sortare;
Aceastconstrucie este similarcelei oferite de limbajul C prin inter-
mediul operatorului &(address-of). Dereferenierea se realizeazcu ajutorul
operatorului $.
De asemenea, se poate folosi construcia "*" pentru a defini un typeglob.
Un typeglob(tip global) poate fi privit la un substitut al tuturor variabilelor
care poartacelai nume, iar atunci cnd este evaluat, un typeglobreturnea-
zo valoare scalar care reprezint toate obiectele Perl purtnd numele
respectiv (e.g.scalari, tablouri, descriptori de fiier, subrutine).
Pentru o variabil, putem preciza scopul(sau domeniul vizibilitii ei). n mod
normal, orice variabilfolositundeva ntr-un program va fi accesibil (vizibil)
oriunde n cadrul acelui program. Pentru a limita vizibilitatea unei variabile, vom
folosi una dintre urmtoarele declaraii:
mydeclaro variabilca fiind disponibildoar n cadrul bloculuide instruciuni curent, n interiorul unei subrutine sau n cadrul unui
eval(). Pot fi declarate cu mydoar variabile scalare sau tablouri (indexate
ori asociative). local este similar cu my, cu excepia faptului cvariabila va fi
disponibildinamic n cadrul unui bloc, subrutine sau eval(). O variabil
localva salva valoarea variabilei globale cu acelai nume i o va restaura
la prsirea blocului, subrutinei sau construciei eval()n care a fost de-
clarat.
Un exemplu de utilizare a declaraiei local:
$numar = 5;
print "Inainte: $numar\n";
-
7/22/2019 Program Are Perl
16/70
16
{
local $numar;
for ($numar = 2; $numar
-
7/22/2019 Program Are Perl
17/70
17
..este operatorul de definire a unui interval, putnd fi utilizat ncontextul listelor de numere sau irurilor de caractere:
# afisarea valorilor de la 1 la 33
print (1..33);# toate combinatiile de la 'aa' la 'zz'
@combinatii = ('aa'..'zz');
# ultimele 3 limbaje
print @limbaje[-3..-1];
Pentru compararea valorilor numerice se vor utiliza operatorii relaionali ,
=, ==i !=(ca n C). Pentru a compara iruri de caractere se vor folosi ope-
ratorii lt, gt, le, ge, eqi ne(ca n Fortran). Aceti operatori vor returna 1 pen-
tru valoarea logic"adevrat" i ""(irul vid) pentru valoarea logic"fals". Se mai
poate folosi pentru valori numerice care va returna -1 dacoperandul stngeste mai mic dect cel drept, 0 dac operanzii sunt egali i +1 dacoperandul
stng este mai mare ca operandul drept. Pentru iruri de caractere, n loc de
vom folosi cmp.
-
7/22/2019 Program Are Perl
18/70
18
Observaii
Operatorul de autoincrementare ofero funcionalitate suplimen-tarputnd incrementa i un ir de caractere:
print ++($grupa = 'g1'); # afiseaza 'g2'
Operatorul unar - poate fi utilizat, de asemenea, pentru iruri,producnd acelai ir, dar prefixat de caracterul "-":
$unu = "unu";
$minus_unu = -"unu";
n Perl, existo multitudine de operatori unari care la prima vede-re par funcii; astfel, sin, cos, log, int, rand, oct, hex, exists,
delete, glob, ref, my, return sau exit sunt de fapt operatori unari.
Astfel, putem snu ncadrm argumentele ntre paranteze, cele doulinii
fiind echivalente:
$valoare = hex "CB74";
$valoare = hex("CB74");
Utilizarea lui existsca operator poate fi urmritn continuare:
print "Grupa exista\n" if exists $grupe{"grupa3"};
Operatorii pe bii pot fi utilizai nu numai pentru ntregi, ci i pen-tru celelalte tipuri scalare:
# vom obtine "020.44"
print "123.45" & "234.56"
Operatorii logici ||i &&(similari cu cei din C) nu vor returna 0sau 1, ci ultima valoare evaluat. De asemenea, pot fi folosii, avnd ace-
eai semantic, operatorii ori and(desigur, n loc de operatorul negaielogic!poate fi utilizat not).
open(FISIER, "index.html") ||
die "Fisierul nu poate fi deschis\n";
Perl pune la dispoziie i operatorii de asignare, astfel nct urm-toarele construcii sunt echivalente (unde OPeste un operator Perl):
$variabila OP= $valoare;
$variabila = $variabila OP $valoare;
-
7/22/2019 Program Are Perl
19/70
19
instruciunilelimbajului n Perl sunt n fapt expresii evaluate pentru efectelelor colaterale. O secvende instruciuni formeazun scop denumit bloc, n gene-
ral un bloc fiind delimitat de paranteze, fiecare instruciune a blocului
terminndu-se cu ";". n afarde instruciuni, un program Perl mai poate cuprin-de declaraiicare pot fi vzute drept instruciuni dar care sunt efective la momentul
compilrii, nu la rulare. Explicit, trebuie declarate obligatoriu numai declaraiile de
formate i de subrutine (dupcum vom vedea mai jos).
Ca i n alte limbaje, instruciunile pot fi grupate n instruciunile de asignare, in-
struciunile de testi instruciuni de control.
Pentru instruciunile de test sau cele iterative, trebuie s precizm faptul c
pentru obinerea valorilor logice ntotdeauna se va evalua n cadrul unui context
scalar. Regulile sunt:
Orice ir de caractere este evaluat la valoarea "fals" daceste vid("") sau conine caracterul zero ("0");
Orice numr este evaluat ca "fals" dac are valoarea 0(sau 0.0);
Orice referineste adevrat; Orice valoare nedefinitse considera fi fals.
Majoritatea instruciunilor sunt similare celor din limbajele C sau Java, cu pre-
cizarea faptului catt if, ct i for sau whilenecesitprezena obligatorie a
acoladelor. Astfel, urmtoarea linie este corectn C, dar genereazeroare n Perl:
if ($nr_studenti >= 30)
printf ("Prea multi studenti...\n");
n loc de elseifla o instruciune ifimbricatse va scrie elsif.
O instruciune specificlimbajului Perl este unless(complementara lui if) fi-
ind echivalentcu un ifavnd condiia de test negat:
unless ($nr_studenti < 30) {
print "Prea multi studenti...\n";
}
Mai natural, putem scrie instruciunile ifi unlessn forma postfixat:
print "Prea multi studenti...\n" if ($nr_studenti >= 30);
$nr_studenti-- unless $nr_studenti;
La fel, instruciunea de ciclare whilepoate fi scrisastfel:
$nr_studenti++ while $nr_studenti < 30;
-
7/22/2019 Program Are Perl
20/70
20
Complementara lui while este until, putnd fi folosit n conjuncie
cu do:
do {
$linie = ;# prelucreaza linia...
} until $linie eq ".\n";
Alturi de for, avem la dispoziie foreach, utilizatmai ales la iterarea tablou-
rilor, dupcum am vzut. Expresia din parantezeste ntotdeauna evaluatca lis-
t, fiecare element al acesteia fiind atribuit pe rnd variabilei de ciclu. Variabila de
ciclu este o referina listei, nu o copie a acesteia. Astfel, modificnd ntr-un ciclu
foreachvariabila de ciclu vom asista la modificarea tabloului pe care l itereaz:
@note = (9, 9, 7, 10, 5, 8, 8);foreach $nota ( @note ) {
print "$nota\n" unless $nota != 10;
$nota++;
}
print "@note\n";
Instruciunile while, fori foreachpot include o instruciune continue(fo-
lositrareori) care va defini un bloc de instruciuni ce va fi executat de fiecare da-
tcnd s-a terminat blocul precedat de cuvntul cheie whilesau la comanda ex-
plicitde trecere la urmtoarea iteraie.De exemplu, codul:
for ($grupa = 1; $grupa < 5; $grupa++) {
print $grupe{$grupa};
}
este echivalent cu:
$i = 1;
while ($grupa < 5) {
print $grupe{$grupa};
}
continue {
$grupa++;
}
Dupcum se poate remarca, semantica lui continuen Perl diferde cea a in-
struciunii continuea limbajului C.
Pentru a modifica fluxul firesc de iterare al unui ciclu, se pot folosi next i
last. Comanda next (similar instruciunii continue din C ori Java) permitesaltul la sfritul blocului de instruciuni i nceperea urmtoarei iteraii. Comanda
-
7/22/2019 Program Are Perl
21/70
21
last(similarcu breakdin C) va termina complet ciclul asupra cruia se aplic.
Mai poate fi utilizati redocare restarteazo iteraie, fra se evalua din nou
condiia (blocul continue, dacexist, nu este executat).
Un exemplu (a doua grupnu va fi afiat):
for ($grupa = 1 ; $grupa
-
7/22/2019 Program Are Perl
22/70
22
Modelul de pasare a parametrilor de intrare i ieire este simplu: toi parametrii
unei subrutine sunt transmii prin intermediul unei liste de scalari, iar eventualele
valori multiple returnate sunt disponibile tot ca listde scalari, cu conversii auto-
mate de tipuri (daceste cazul). Parametrii pasai oricrei rutine Perl vor fi regsiica tablou n variabila special$_. Orice operaiune cu tablouri poate avea loc, de-
sigur, i asupra acestei variabile. Acest lucru asigurpasarea unui numr variabil
de parametri. Mai mult, pentru a avea acces indexat la parametri specifici, putem
folosi indici (e.g.$_[0]pentru primul argument sau $_[2]care l desemneazpe
cel de-al treilea). Un anumit parametru poate fi testat daceste definit cu ajutorul
funciei defined(). Putem furniza parametri nedefinii cu ajutorul lui undef:
select (undef, undef, undef, $timp);
Pentru ca o rutinsreturneze valori codului apelant, vom folosi return(dactrebuie transmis un tablou, vom utiliza return @_).
Fiecare subrutinpoate include variabile private declarate cu my. n Perl subru-
tinele pot fi apelate recursiv, ca i n alte limbaje.
Limbajul Perl pune la dispoziia programatorilor o palet larg de funcii
predefinite. n cadrul programului prezentat la nceputul acestui sub-capitol, se ob-
servutilizarea funciei predefinite printfpentru a afia formatat diverse date.
O alt funcie des folosit este print (aceast ultim funcie nu realizeaz i
formatarea fixa datelor).
-
7/22/2019 Program Are Perl
23/70
23
Prelucrarea fiierelor i directoarelor
Manipularea fiierelor la nivelul sistemului se realizeazuzual prin intermediul descripto-
rilor de fiier. Un descriptor de fiier desemneazo conexiune de intrare/ieire ntre pro-gramul Perl i sistemul de operare.
Ca i alte limbaje de programare, Perl pune la dispoziie trei descriptori de fiier care
sunt preluai de la procesul printe al interpretorului de comenzi i sunt asociai dispozi-
tivelor de intrare/ieire deja deschise de acesta: STDIN, STDOUTi STDERR. Aceti descrip-
tori de fiiere au aceeai semnificaie ca stdin, stdouti stderrdin limbajul C sau de-
scriptorii 0, 1, respectiv 2 din bash.
Pentru numele descriptorilor de fiiere limbajul Perl rezervun spaiu de nume sepa-
rat: aa cum putem avea o variabilscalar$x, un tablou @x, un tablou asociativ %x, o
subrutinxetc., n acelai program putem avea i descriptorul de fiier x, frnici un pe-
ricol de confuzie.
Descriptorii STDIN, STDOUT i STDERRpot fi utilizai fr a-i deschide, pentru c ei
sunt implicit deschii.
Pentru citirea unui ir de caractere de la intrarea standard, folosind STDIN, vom recur-
ge la funcionalitatea oferitde operatorul "".
print STDOUT "Un nume, va rugam: ";
$nume = ;
print STDOUT "Salut, $nume.\n";
n acest exemplu remarcm i specificarea explicita descriptorului STDOUT ca argu-
ment al funciei print(). n variabila $numevor fi stocate caracterele preluate de la in-
trarea standard, inclusiv caracterul newlinecare marcheazfinalul introducerii irului de la
terminal. Uneori este de dorit ca acest ultim caracter sfie eliminat. Pentru a realiza acest
lucru vom apela funcia predefinitchop():
$nume = ;chop($nume);
print "Salut, $nume.\n";
O altfuncie utileste chomp()care va terge toate caracterele newlinede la sfritul
parametrului primit i va returna numrul de caractere eliminate.
Operatorul "" poate fi folosit pentru orice descriptor de fiier. n conjuncie cu o
variabilscalarva realiza citirea unei linii de fiier. De asemenea, poate fi utilizat ntr-o
atribuire a unui tablou, caz n care se va citi ntreg con inutul unui fiier, fiecare element
al tabloului reprezentnd o linie a acelui fiier:@linii =
-
7/22/2019 Program Are Perl
24/70
24
La fel, funcia print()poate avea ca prim argument un descriptor de fiier (vezi i
exemplele de mai jos).
Dacnu se specificnici o variabil, atunci operaiile de intrare/ieire se vor realiza
prin intermediul variabilei speciale $_. O altvariabilpe care o putem folosi este $.careva indica numrul curent al liniei dintr-un fiier, numerotarea pornind de la 1.
Similar altor limbaje, deschiderea unui fiierse realizeazcu ajutorul subrutinei open()ca-
re acceptunul, doi sau trei parametri:
open (DESCRIPTOR)
open (DESCRIPTOR, NUMEFIS)
open (DESCRIPTOR, MOD, NUMEFIS)
DESCRIPTOR este descriptorul asociat numelui de fiier (numele fiierului poate avea
mai multe semnificaii, dup cum vom vedea mai jos), NUMEFIS reprezint numele de
fiier cruia i se asociazdescriptorul DESCRIPTOR, iar MODspecificmaniera n care va fi
deschis fiierul. NUMEFISnu semnificneaprat numele unui fiier din sistemele de fiiere
locale sau montate prin reea.
n primul caz variabila $DESCRIPTOR conine numele fiierului, iar dup apelarea lui
open $DESCRIPTORva fi alocat i un descriptor de fiier cu acelai nume.
Mod Descriere Echivalent C
Trunchiere i scriere, cu posibilitatea citirii "w+"
>> Scriere, adugare la sfrit "a"
Modurile n care pot fi deschise fiierele
nchiderea unui fiierse realizeazcu subrutina predefinitclose()care primete ca unic
argument descriptorul de fiier dorit a fi nchis.
Un exemplu de deschidere, citire i nchidere a unui fiier este urmtorul:# parcurgem /etc/passwd
-
7/22/2019 Program Are Perl
25/70
25
my $DESCRIPTOR;
my $NUMEFIS="/etc/passwd";
open (DESCRIPTOR, "
-
7/22/2019 Program Are Perl
26/70
26
if $gid < 90;
}
close(INPUT);
close(OUTPUT);
Acelai rezultat se poate obine prin duplicarea descriptorului de fiier corespunztor
ieirii standard:
my ($INPUT, $OUTPUT);
my $infile="/etc/passwd";
open (INPUT, "&STDOUT")
|| die "Nu pot duplica STDOUT: $!\n";
open (STDOUT,"|-","sort -u")
|| die "Nu pot lansa comanda sort: $!\n";
my ($username, $passwd, $uid, $gid, $gecos, $home, $shell);
while () {
($username, $passwd, $uid, $gid, $gecos, $home, $shell)
= split(/:/);
print "$username are drepturi de root.\n"
if $uid == 0;
print "$username este un utilizator privilegiat.\n"
if $gid < 90;
}
close(INPUT);
close(STDOUT);
open(STDOUT, ">&OLDOUT");
Un alt exemplu, n care vom afia linie cu linie coninutul unui fiier, fiecare linie fiind
precedatde numrul ei, este:
while() {
print "$. : $_";
}
Operatorul "" poate fi utilizat i fr a specifica un descriptor, n acest caz citirea
efectundu-se de la intrarea standard.
Se pot folosi, de asemenea, funciile uzuale seek(), tell()i flock(), similare celor
din limbajul C.
Pentru prelucrarea coninutului directoarelor exist un set de funcii diferite de cele
destinate operrii cu fiiere. Astfel, opendir(), closedir(), seekdir(), telldir()
au corespondeni similari printre funciile pentru lucrul cu fiiere. Funcia rewinddir()poate fi suplinitprintr-un apel al lui seekdir().
-
7/22/2019 Program Are Perl
27/70
27
Exemplu de citire a coninutului unui director (simuleazcomanda ls):
my ($DIR, $dirname);
die "Avem nevoie de cel putin un argument!\n"
unless (defined($dirname = $ARGV[0])&& $dirname ne "");
opendir(DIR,$dirname)
|| die "Nu putem deschide directorul $dirname: $!\n";
my $file;
my $raspuns = "y";
while (defined($raspuns) && $raspuns=~/y|d/i) {
rewinddir(DIR);
while ($file = readdir(DIR)) {
print "$file\n";}
print "Mai afisam inca odata acestui director?";
$raspuns = ;
}
closedir(DIR);
Permisiunile unui fiier pot fi setate folosind funcia chmodcare primete aceeai pa-
rametri ca apelul de sistem similar din C.
Alte funcii predefinite pentru lucrul cu fiiere i directoare sunt mkdir(), chdir(),
rename(), rmdir(), chown(), fileno(), ioctl(), lstat(), link(), symlink() iunlink(). Apelul lor n Perl este similar cu cel din limbajul C.
Pentru a testa existena sau tipul unui fiier, n limbajul Perl se pot folosi, de asemenea,
construcii similare celor din bash. Cteva exemple:
print "Dati un nume de fisier: ";
$nume = ;
chomp $nume;
if ( -r $nume && -w $nume ) {
print "$nume poate fi citit/scris.\n";}
O altfacilitate oferiteste cea a expandrii coninutului unui director folosind specifi-
catori de fiier. n Perl acest lucru se realizeazfie cu ajutorul operatorului "", fie prin
intermediul funciei predefinite glob()i poartnumele deglobbing.
@pagini = ;
@pagini = glob("*.html");
Dupcum se observ, am folosit meta-caracterul "*" pentru a genera o listcu numele
tuturor fiierelor .htmldin directorul curent.
-
7/22/2019 Program Are Perl
28/70
28
Un alt exemplu, n care tergem toate fiierele stocate n directorul /tmp:
foreach () {
unlink || warn "Eroare la stergerea $_: $!\n";
}
Semnalarea erorilor i avertismentelor
Din cele de mai sus se poate remarca faptul capelarea unor funcii precum open()se
realizeazn conjuncie cu operatorii orsau ||pentru a verifica dacsurvin erori i a in-
dica natura lor.
n cazul unei erori fatale putem apela die()care oprete forat execuiaprogramului, afind mesajul specificat ca argument. Codul de eroare poate fi
capturat prin intermediul variabilei speciale $!. Dacmesajul nu este terminat decaracterul "\n", atunci funcia die()va afia i numrul liniei de program care a
cauzat eroarea.
O funcie nrudit este warn()care nu va opri execuia programului, cidoar va afia irul primit ca argument, considerndu-l mesaj de avertisment:
open(LOG, ">>httpd.log") ||
warn "Eroare la deschidere: $!";
-
7/22/2019 Program Are Perl
29/70
29
1.4 Expresii regulate
Pentru a nelege funcionalitatea programului prezentat la nceputul acestei seciunimai trebuie sne referim la una dintre cele mai interesante faciliti oferite de limbajul
Perl: expresiile regulate(pentru fundamentele teoretice ale expresiilor regulate, cititorul inte-
resat poate parcurge cartea T. Jucan, Limbaje formale i automate, Editura MatrixRom, Bu-
cureti, 1999). n fapt, existun numr larg de utilitare i aplicaii care ncorporeazex-
presiile regulate ca parte a funcionalitii interne a respectivelor programe: comenzile
UNIX/Linux de procesare a liniilor (grep, sedsau awk) sau chiar shell-urile din sistem.
n afarde Perl, i alte limbaje ofersuport direct pentru expresii regulate, putem da ca
exemple Python ori Tcl.O expresie regulatreprezintun ablon(pattern) cruia, pe baza unor reguli precise, i se
poate asocia unui text.
Pentru lucrul cu expresiile regulate, limbajul Perl pune la dispoziie mai muli operatori
care, pe lngrolul de delimitare, oferun set de opiuni pentru cutare i/sau substituie
n cadrul unui text.
Variabila implicitn care se realizeazdiferite aciuni implicnd expresii regulate este
$_, iar specificarea altei variabile se realizeazprin intermediul operatorului "=~".
De notat faptul c, n primele exemple de utilizare pe care le vom da, se vor folosi
drept expresii regulate simple iruri de caractere. Pentru a manipula expresii regulate, ne
vom sluji de o serie de operatori descrii n continuare.
Operatorul m//
Acest operator se folosete pentru a cuta un ablon n cadrul unui text dat. Deoarece
de cele mai multe ori nu existnici un pericol de confuzie, caracterul "m" care preced
expresia este opional. Se returneazvaloarea logic"adevrat" n cazul n care cutarease ncheie cu succes, "fals" n rest (putem aadar s-l folosim n cadrul expresiilor logice).
# atita timp cit se introduce ceva de la tastatura
while () {
print "Am gasit subsirul \"Victor\" in $_"
if m/Victor/;
}
-
7/22/2019 Program Are Perl
30/70
30
Cea mai utilizate opiuni ale acestui operator sunt:
i- cutare case-insensitive(majusculele nu diferde minuscule):while () {print "Am gasit tag-ul \"\" sau \"\" in $_"
if //i;
}
g- cautn ir toate secvenele care se potrivesc ablonului:my $sir = "a b r a c a d a b r a";
my $num_a = 0;
while ($sir =~ /a/g) {
$num_a++;
}print "Am gasit de $num_a ori caracterul \'a\'.\n";
# va afisa "Am gasit de 5 ori caracterul 'a'."
o- evalueazablonul doar o singurdat. Folosirea lui n cutri succesi-ve n acelai ablon are ca efect creterea vitezei de cutare.
while () {
print if /$ARGV[0]/o;
}
x- permite utilizarea de spaii albe i comentarii n cadrul expresiei regula-te cu scopul de a face codul mai lizibil:
while () {
print if /^e x\ tins # tipareste daca linia incepe
# cu 'ex tins'
/sx;
}
n acest exemplu spaiul dinaintea caracterului "#" care precede un comentariu
va fi ignorat, la fel ca i spaiul dintre "e" i "x", dar nu i spaiul alb precedat de
un caracter "\" dintre "x" i "t".
Operatorul s///
Operatorul s/ablon/text/ permite cutarea i substituia unui ablon cu
un text.
Un exemplu:
while () {
s/autmat/Automat/i;
print;
-
7/22/2019 Program Are Perl
31/70
31
}
Va nlocui cuvntul autmatdat la intrarea standard cu Automati va scrie toate liniile
citite la ieirea standard indiferent dacsubstituia s-a efectuat sau nu.
Operatorul qr//
Acest operator primete ca parametru un ir de caractere pe care l precompileazca
expresie regulat. Expresia regulat precompilat poate fi memorat ntr-o variabil i
refolositn construcia altor expresii regulate sau poate fi utilizatdirect:
my $expr = qr/(autmat|automt)/i;
# exemplu de folosire directa
while () {
s/$expr/Automat/;
print;
}
my $expr=qr/(autmat|automt)/i;
# exemplu de folosire in alte constructii
while () {
s/altceva\ $expr\ nimic/Altceva\ Automat\ ceva/;
print;
}
Am utilizat construcia escape"\ " pentru ca spaiul snu fie interpretat. Putem prece-
da cu backslashorice caracter avnd semnificaie aparte pentru a nu mai fi special proce-
sat.
De remarcat faptul c operatorii m//, s/// vor folosi valoarea variabilei $_ pentru
cutarea ablonului dacnu este utilizat nici unul dintre operatorii =~sau !~.
Delimitarea expresiei regulate i, daceste cazul, a irului substituitor se poate realiza
cu alte caractere speciale dect "/". Astfel, secvena de cod de mai jos este perfect valabi-
l:my $text = "123 /abc XYZ";
# inlocuim "/abc" cu "AbC"
print "$text\n" if $text =~ s!/abc!AbC!;
Expresia se mai putea scrie i s#/abc#AbC#sau s|/abc|AbC|ori s@/abc@AbC@.
Un alt exemplu, care va afia coninutul tuturor elementelor dintr-un document
HTML (caracterul "/" nu mai putea fi folosit ca delimitator de expresie regulat):
while () {
print if m##i .. m##i;
}
-
7/22/2019 Program Are Perl
32/70
32
n acest exemplu, remarcm i utilizarea operatorului ..care se dovedete extrem de
util aici pentru extragerea unui interval de linii fra se reine explicit aceste informaii.
Secvene pentru identificarea unui caracter. Multiplicatori
Cel mai simplu mod de a identifica un anumit caracter n cadrul unui text este cel de a
cuta exact acel caracter. Scrierea unui caracter "a" ntr-o expresie regulat presupune
existena aceluiai caracter n irul cruia i se aplica.
De multe ori nsam dori sfolosim diverse meta-caractere pentru a identifica un set
de caractere.
Meta-caracterelesunt acele caractere din codul ASCII care nu se identificpe ele nsele n
cadrul unei expresii regulate sau chiar al unei secvene de cod-surs (scris n C/C++,Perl etc). n cadrul unei expresii regulate meta-caracterele sunt folosite pentru alctuirea
unor construcii cu rol de a identifica diferite secvene de caractere dintr-un text.
Urmtoarele caractere ASCII sunt considerate meta-caractere n cadrul unei expresii
regulate:
Caracterul "." este utilizat n cadrul unei expresii regulate s identificeorice caracter, exceptnd caracterul newline"\n".
Construcia "[...]" reprezinto clasde caractere. De exemplu expresiaregulat/[a-z]/se poate asocia oricrui ir de caractere care conine cel puin o
literminuscul. Bineneles, se pot concepe construcii mai complexe, cum ar fi
/[a-z][ATX][0-7]\-[^1-378]/ care va identifica orice text coninnd o suc-
cesiune de caractere format, n ordine, de o literminuscul, una dintre majuscu-
lele "A", "T" sau "X", o cifrntre 0 i 7, semnul minus "-" i oricare cifrdiferit
de 1, 2, 3, 7 sau 8. De exemplu, comparaia dintre irul %0bX7-0Fcomparat cu
expresia regulatde mai sus se va finaliza cu succes datoritsubirului bX7-0.
Meta-caracterul "^" are douroluri: Folosit n cadrul unei secvene de caractere are rolul de negare.
Astfel, [^2-5]va identifica oricare cifraparinnd mulimii {1, 6, 7, 8, 9,
0}, iar [^a-m]va identifica oricare caracter cu excepia minusculelor de la
"a" la "m".
Desemneaznceputul unei linii, fiind un caracter de poziionaren rest. De exemplu, ^[2-5]va identifica orice ir care ncepe cu o cifr
cuprinsntre 2 i 5.
Precedat de un "\" va desemna caracterul "^".
-
7/22/2019 Program Are Perl
33/70
33
Simbolul "$" folosit ntr-o expresie regulat identific sfritulunei linii.
Caracterele "(" i ")" au rolul de a grupa atomi n cadrul expresiei regula-te i de a memora valoarea subirurilor din text corespunztoare acestor atomi,frnsa modifica valoarea expresiei regulate (aceastconstrucie se mai nume-
te i operator de memorare). Un caracter lipsit de semnificaie sau un meta-
caracter de poziionare (e.g."^" sau "$") se numete atomal unei expresii regulate.
Putem grupa atomi pentru a forma fragmente ale unei expresii regulate mai com-
plexe.
Fie script-ul:
my ($LOG, $i);
open(LOG, ">>/tmp/word_switch.log") ||
die "Nu pot deschide fisierul: $!\n";
while () {
$i++;
s/^(\S+)\s+(\S+)/$2 $1/;
print;
print LOG "linia $i: s-a inversat \"$1\" cu \"$2\"\n";
}
close(LOG);
Acest program va prelua linii de text de la intrarea standard i va afia la ieireastandard inversnd primele doucuvinte ntre ele, scriind ntr-un fiier modific-
rile efectuate.
Caracterul "|" va da posibilitatea de a alterna ntre dou sau mai multeforme posibile ale unei secvene dintr-un text.
while () {
print if (/[0-9]|[A-Z][a-z]/);
}
Urmtorul scriptva putea identifica orice ir care conine un subir format saudintr-o literminusculurmatde cel puin o cifr, sau dintr-o cifrsuccedatde
cel puin o majuscul. Subirul care se potrivete ablonului va fi tiprit:
while() {
print "\"$1\" se potriveste sablonului\n"
if (/([a-z]\d+|\d[A-Z]+)/);
}
Meta-caracterele "?", "*, "+, "{" i "}" au rolul de multiplicatori ai unuiatom.
-
7/22/2019 Program Are Perl
34/70
34
Un atom al unei expresii regulate urmat de "?" poate identifica dezero sau maxim o singurdatun atom;
Simbolul "*" poate identifica zero, una sau mai multe apariii con-secutive ale aceluiai atom;
Un atom urmat de "+" poate sidentifice mcar o apariie a ato-mului.
Un exemplu:
while () {
print "Cel putin o aparitie a cuvintului \'web\'
la inceputul liniei\n"
if (/^(web)+/);
}
Multiplicatorul "{}" are o sintax ceva mai complex dect "*" i
"+", astfel:
atom{m, n}va identifica ntr-o expresie cel puin matomi, dar numai muli de n;
atom{m,}va identifica msau mai muli atomi; atom{,n}va identifica natomi cel mult; atom{n}va identifica exact natomi.
Putem face aici observaia c{1,} este echivalent cu "+", {0,1} cu "?", iar
construcia {0,}este echivalentcu "*". Valorile lui mi nsunt n intervalul [0,
65535].
Dacmeta-caracterul "?" urmeazunui multiplicator, acesta din urmva avea
un caracter ponderat (minimal).
Limbajul Perl pune la dispoziie un set de construcii predefinite pentru identificarea
unor clase de caractere, dupcum se poate remarca din tabelul urmtor.
-
7/22/2019 Program Are Perl
35/70
35
Construcie EchivalentConstrucie
complementar
Echivalentul construciei
complementare
\d
(o cifr)[0-9]
\D
(orice
exceptnd cifre)
[^0-9]
\w
(un caracter alfanumeric)[0-9_a-zA-Z]
\W(un caracter
ne-alfanumeric)[^0-9_a-zA-Z]
\s
(un spaiu alb)
[\t\r\n\ \f
]
\S
(orice exceptnd
spaii albe)
[^\t\n\r\ \f]
Identificarea claselor de caractere
Expresia regulat /(.*\d+[A-Z]{3,7})/ poate identifica orice ir de caractere cu
urmtoarea componen: ncepe cu oricare caracter(e), continucu cel puin o cifri se
termin cu cel puin trei majuscule, dar nu mai mult de apte. Totui un ir de forma
abc123ABCDEFGHIJKL se va potrivi acestei expresii regulate, condiiile impuse fiind satis-
fcute, n variabila $1 (s-a folosit () - operatorul de memorare) fiind stocat irul
123ABCDEFG. Dacnsla sfritul acestei expresii mai adugm o constrngere (final delinie, de exemplu, sau alt caracter) multiplicatorul {}va fi forat sse opreasc.
Construcia /(\d+[A-Z]{3,7})\;/ va fora ca n componena irului snu existe mai
mult de apte majuscule, nici mai puin de trei, i, mai mult, sfie urmate de caracterul
";".
Toi aceti multiplicatori prezentai mai sus vor identifica att de muli atomi ct este
posibil. Astfel, [A-Z]{3,7}n prima varianta exemplului prezentat dupce va gsi n
text trei majuscule, va continua cutarea i se va opri la apte daceste posibil. De ase-
menea, \d+a identificat toate cele trei cifre din text, dei o posibilvarianta valorii lui
$1ar fi fost 23ABCDEFG.
n cazul prezenei n expresia regulata doi (sau mai muli) multiplicatori, cel mai din
stnga va identifica mai multe caractere n detrimentul celorlali aflai mai n dreapta.
Considerm o variantpuin modificata expresiei de mai sus i anume /^.*(\d+[A-
Z]{3,7})/. Forma textului pe care l va identifica nu se schimb, nstextul memorat n
$1difern situaiile n care vor exista mai mult de doucifre. Folosind n continuare i-
rul abc123ABCDEFGHIJKL , valoarea stocatde $1va fi 3ABCDEFG.
-
7/22/2019 Program Are Perl
36/70
36
Existsituaii cnd un asemenea comportament al multiplicatorilor nu ne convine. S
considerm expresia regulat/(a.*bc)/i textul dd a ddd bc dddd bc bdd. O com-
paraie ntre acest ir i /(a.*bc)/va avea ca rezultat memorarea n $1a valorii a ddd
bc dddd bc. Se observcdei compararea s-ar fi putut opri dupprima pereche bc, acontinuat. n acest caz compararea s-a fcut pnla sfritul irului de caractere, dar nefi-
ind ndeplinite condiiile de identificare s-a revenit la ultima succesiune de caractere "po-
trivit".
Ali identificatori de caractere
Limbajul Perl mai pune la dispoziie, alturi de construciile predefinite pentru identifi-
carea unor clase de caractere, i construcii conforme cu standardul POSIX, de forma
[:clasa_de_caractere:], utilizate i de funciile PHP.
Clasele de caractere (care pot fi utilizate ca mai sus) sunt: alpha, alnum, ascii,
cntrl, digit, graph, lower, print, punct, space, upper, wordi xdigit. Caracterele
incluse n aceste clase de caractere sunt cele pentru care funciile C cu numele is-
clasa_de_caractere()returneaz"adevrat".
Astfel, [[:alnum:]]este echivalentcu [0-9a-zA-Z], [[:word:]]este echivalent
cu [0-9a-zA-Z_], [[:digit:]]cu [0-9]etc.
De asemenea, limbajul Perl definete construcii cu lungime nul (zero-width assertions)care identificdoar contexte, nu caractere, n urmtorul mod:
\bidentificlimitele unui cuvnt; \B identificorice alt context dect limitele unui cuvnt (interiorul unui
cuvnt);
\Adesemneaznceputul unui ir; \Zidentificsfritul unui ir sau naintea caracterului newlinede la finalul
irului; \zidentificsfritul unui ir; \Gva identifica locul unde are loc ultima potrivire a ablonului n text, n
cazul folosirii opiunii /ga operatorilor m//sau s///.
De exemplu "/text\b/" poate identifica " text", "text", "context", dar nu i
"textul".
-
7/22/2019 Program Are Perl
37/70
37
Utilizarea variabilelor n expresiile regulate
Operatorii delimitatori care ncadreazexpresiile regulate au un comportament asem-
ntor ghilimelelor (double quote). Astfel, ca i n alte cazuri, variabilele care intrn compo-
nena unui ablon sunt evaluate la fiecare evaluare a acestuia n vederea cutrii n text.
Excepie fac expresiile regulate delimitate de ghilimele simple (single quotes) care inhib
evaluarea sau n cazul folosirii opiunii /ocare ne asigura de faptul cacea expresie regu-
lateste compilatdoar o singurdat.
Foarte util n unele cazuri ale utilizrii variabilelor n cadrul expresiei regulate se dove-
dete operatorul qr//. Un exemplu de folosire al lui qr// n acest caz este evaluareaunor pri ale unei expresii regulate numai o singurdat, artificiu care poate mri viteza
de procesare a unor texte folosind expresii regulate complexe avnd pri care rmn ne-
schimbate mai mult timp:
my ($text_de_inlocuit, $text_inlocuit, $expresie);
print "Ce text vom inlocui in text? ";
chomp($text_inlocuit = );
print "Cu ce text vom inlocui \"$text_inlocuit\"? ";chomp($text_de_inlocuit = );
$expresie = qr/$text_inlocuit/;
while () {
s/$expresie/$text_de_inlocuit/i;
print;
}
-
7/22/2019 Program Are Perl
38/70
38
Funcii predefinite folosind expresii regulate
n conjuncie cu expresiile regulate se pot utiliza urmtoarele funcii predefinite:
tr/// realizeaz translatarea caracter cu caracter a unui text iare forma:
tr/caractere_de_cutare/caractere_de_nlocuire/
Aceastfuncie mai poartnumele i de funcie de transliterare.
irul de intrare este parcurs caracter cu caracter, nlocuindu-se fiecare apariie a
unui caracter de cutare cu corespondentul lui din mulimea caracterelor de nlo-
cuire.
Se pot folosi opiunile:
c- va realiza translatarea utiliznd complementara mulimii de ca-ractere de cutare;
d- va terge toate caracterele din mulimea caracterelor de cutarecare nu au corespondent n setul caracterelor de nlocuire;
s - va reduce secvenele de caractere care au fost nlocuitefolosindu-se acelai caracter la o apariie unica caracterului respectiv.
Cteva exemple:
# majusculele devin minuscule
tr/A-Z/a-z/
# http: devine ftp:
tr/http:/ftp:/
# caracterele diferite de alfanumerice devin spatii
tr/A-Za-z0-9/ /cs
split() mparte un ir de caractere n funcie de o expresie regulatireturneazun tablou coninnd subirurile care nu satisfac acea expresie regulat.
Dupcum vom vedea n seciunea 2.1, funcia va fi foarte folositoare pentru rea-
lizarea de script-uri CGI.
Pentru a afia numele de cont i directorul homeal utilizatorilor din sistem vom
putea scrie urmtorul script(folosim fiierul /etc/passwd).
open (FIS, "/etc/passwd") ||
die "Eroare la deschiderea fisierului\n";
while () {
$linie = $_;
chomp($linie);
-
7/22/2019 Program Are Perl
39/70
39
@date = split(':', $linie);
($cont, $dir) = @date[0, 6];
print "Directorul home al lui $cont este $dir\n";
}
close (FIS);
Elementele returnate de split()se pot memora i n variabile scalare separa-
te. Astfel, pentru a stoca data sistem vom putea scrie urmtoarele linii de cod:
$data_sistem = localtime(time);
($ziua, $luna, $num, $timp, $an) = split(/\s+/, $data_sistem);
join() este complementar funciei mai sus amintite, n sensulc reunete mai multe iruri de caractere n unul singur, delimitate de
un scalar.
Un exemplu:
$perl = "Perl";
$cpp = "C++";
$java = "Java";
$tcl = "Tcl";
print "Limbaje: ",
join(" ", $perl, $cpp, $java, $tcl), "\n";
print "Limbaje: ",
join(", ", $perl, $cpp, $java, $tcl), "\n";
O variantalternativeste cea care recurge la utilizarea operatorului de conca-
tenare ".", frposibilitatea de a specifica elementul de legtur.
eval() poate fi folosit pentru evaluarea/execuia unei expresii Perl.Contextul execuiei expresiei Perl este contextul curent al programului. Putem
considera expresia ca o subrutinsau bloc de instruciuni n care toate variabilele
locale au timpul de viaegal cu cel al subrutinei ori blocului. Dacnu se specific
o expresie ca argument al funciei, se va utiliza n mod firesc variabila special$_.
Valoarea returnatde eval()reprezintvaloarea ultimei expresii evaluate, fiindpermisi folosirea operatorului return.
Posibilele erori vor cauza returnarea unei valori nedefinite i setarea variabilei
$@cu un mesaj de eroare.
Astfel, eval() poate fi de ajutor n verificarea corectitudinii
unui ablon:
sub este_sablonul_valid {
my $sablon = shift;
return eval { "" =~ /$sablon/; 1 } || 0;
}
-
7/22/2019 Program Are Perl
40/70
40
Putem prentmpina afiarea unui mesaj de eroare la apariia excepiei de m-
prire la zero a unui numr astfel:
print "Impartire la zero"
unless eval { $rezultat = $nr1 / $nr2 };
-
7/22/2019 Program Are Perl
41/70
41
1.5 Modulele Perl
Conceptul de pachet
Modulele(pachetele) Perl reprezintuniti de cod precompilat, ncapsulnd diferite func-
ionaliti oferite programatorilor.
UnpachetPerl poate fi considerat drept implementarea unei clase pe care o putem in-
stania n cadrul unui script. Subrutinele incluse ntr-un pachet pot juca, de asemenea, rolul
de metode, existnd posibilitatea definirii de constructori i destructori. Mai mult, se ofe-
rsuport pentru derivarea unei metode aparinnd unui pachet, astfel nct pachetele Perl
pot fi ierarhizate. Mai multe pachete pot fi grupate n biblioteci.
Vom referi variabilele din alte pachete prefixnd identificatorul variabilei respective cu
numele pachetului urmat de "::", dupcum se poate observa din urmtorul exemplu:
$intrare = $main::STDIN;
La fel, pentru metode:
$imagine = new GD::Image(174, 333);
Dacnu este specificat numele pachetului, se considerimplicit pachetul main. Astfel,
construcia$::var
este echivalentcu$main::var
.Dacdorim s accesm metode sau date-membru definite ntr-un pachet derivat din
altul vom specifica numele ambelor pachete:
$Pachet::Subpachet::variabila
Conceptul de modul
Un modulreprezintun pachet public definit ntr-un fiier .pmcu scopul de a fi reutili-
zat ulterior. Modulele Perl vor fi incluse n program, spre a fi folosite,
prin construcia:
use Modul;
La fel, use Modul ();este echivalent cu require Modul;, dar se recomandutiliza-
rea lui usen favoarea unui require.
Pentru mai multe detalii, cititorul poate consulta paginile de manual pentru perlmodi
perlxs.
Sunt puse la dispoziie mai multe module standard (disponibile n orice distribuie Perl
actual), dintre care se pot meniona:
-
7/22/2019 Program Are Perl
42/70
42
Carp(pentru controlul erorilor i avertismentelor); Config(pentru acces la opiunile de configurare); CGI(pentru generarea facilde script-uri CGI); Env(pentru accesarea variabilelor de mediu); ExtUtils::Embed(pentru includerea de cod Perl n programele C); File::Find(pentru traversarea recursiva unui arbore de directoare); File::Handle(pentru manipularea fiierelor folosind descriptori de fiier); File::Path(pentru operaii cu directoare); Math::Complex(pentru prelucrarea numerelor complexe); POSIX(pentru asigurarea interfeei cu standardul POSIX IEEE 1003.1); Search::Dict(pentru cutarea unei chei ntr-un fiier dicionar); Socket(pentru realizarea de operaiuni cu socket-uri); Time::Local(pentru acces la timpul local).
Pentru a gsi toate modulele instalate n sistem (inclusiv cele care nu au documentaii
sau au fost instalate n afara distribuiei standard) putem folosi urmtoarea linie de co-
menzi:
find `perl -e 'print "@INC"'` -name "*.pm" -print
n mod normal, fiecare modul posedpropria lui documentaie, accesibilprin inter-
mediul comenzii mandin UNIX. Se poate utiliza i comanda perldoc.
CPAN
Succesul limbajului Perl rezid, n principal, din posibilitatea de a extinde limbajul cu
noi funcionaliti oferite de module. n afara modulelor din distribuiile Perl standard,existo colecie globala tuturor materialelor publice referitoare la Perl, colecie referit
sub denumirea CPAN(Comprehensive Perl Archive Network). CPAN oferun numr impre-
sionant de module grupate pe urmtoarele categorii:
extensii de limbaj i unelte de documentare; suport pentru dezvoltare de programe/module; interfee (la nivel sczut sau ridicat) cu sistemul de operare; comunicarea ntre procese, n reea i controlul dispozitivelor
(e.g., modemuri);
-
7/22/2019 Program Are Perl
43/70
43
tipuri de date i conversii; interfee cu bazele de date; interfee cu utilizatorul; interfee cu alte limbaje de programare; procesarea fiierelor i sistemelor de fiiere; procesarea caracterelor; procesarea fiierelor de configuraie i a parametrilor n linia de comand; suport pentru diverse limbi i alfabete (internaionalizare); autentificare, securitate i criptare; suport pentru pota electronici grupurile de tiri; suport pentru Web (HTML, HTTP, CGI, XML etc.); utilitare pentru daemoni; suport pentru arhivarea i compresia datelor; procesarea informaiilor grafice; controlul fluxului (excepii, erori etc.); procesarea fluxurilor de date i a fiierelor; altele.
Pentru un listing al tuturor locaiilor Internet referitoare la CPAN, consultai
http://www.perl.com/perl/ .
Instalarea unui modul
n unele cazuri va trebui slum un modul de la CPAN pentru a-l instala i folosi ulte-rior n cadrul script-urilor noastre. Pentru a fi instalat pe un sistem UNIX/Linux, un mo-
dul Perl se regsete fie ca fiier tararhivat cugzip(deci are extensia .tar.gzsau .tgz),
fie ca fiier .pm(deja dezarhivat).
Orice modul Perl necesit pentru instalare existena interpretorului Perl
n sistem.
Dupdezarhivare (cu tar -xzf numearhiva.tgz), n directorul n care a fost stocat
modulul dorit a fi instalat se dau urmtoarele comenzi (pentru a se putea executa ultima
linie, utilizatorul trebuie saibdrepturi de root):
-
7/22/2019 Program Are Perl
44/70
44
perl Makefile.PL
make
make test
make install
Dacse dorete instalarea unui modul ntr-o altlocaie (de exemplu, n directorul pri-
vat al unui utilizator), atunci se substituie prima linie cu:
perl Makefile.PL INSTALLDIRS=site INSTALLSITELIB=/home/user/director
Pentru a folosi acel modul n programele noastre, va trebui sprefam fiecare scriptcu
liniile de mai jos:
use lib '/home/user/director'
use Modul;
n care /home/user/director este directorul unde a fost instalat modululdenumit Modul.
n mod uzual, fiecare modul este acompaniat i de documentaia necesarexploatrii
lui. Pentru a avea acces la ea, se folosete utilitarul perldoc:
(infoiasi)$ perldoc XML::Parser
Pentru convertirea documentaiei n format text sau HTML se pot utiliza comenzile
pos2texti, respectiv, pod2html, ca n exemplul urmtor:
(infoiasi)$ pod2text Parser.pm >Parser.txt
(infoiasi)$ pod2html Parser.pm >Parser.html
1.6 Exemple simple
Vom furniza n continuare o serie de exemple de rutine Perl folositoare.
Pentru a verifica validitatea unei adrese de e-mail putem recurge la func ia urm-toare:
sub valid_email {$testmail = shift;
return 0 if ($testmail =~/ /);
if ($testmail =~ /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/ ||
$testmail !~
/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/) {
return 0;
}
else {
return 1;
}}
-
7/22/2019 Program Are Perl
45/70
45
Afiarea, linie cu linie, a coninutului unui fiier se poate realiza astfel, prin inter-mediul subrutinei urmtoare:
sub gen_file_content() {
$file = shift;return 1 unless open(FIL, "
-
7/22/2019 Program Are Perl
46/70
46
2. Script-uri CGI n Perl
2.1 Primele script-uri CGI
Standard de facto pentru interaciunea clienilor Web cu serverele Web, Common
Gateway Interfacese afln prezent la versiunea 1.1. Un program CGI, denumit n mod
uzual script, se executpe serverul WWW, fie n mod explicit (apelat din cadrul paginii
printr-o directivspecial), fie la preluarea informaiilor aflate n cadrul cmpurilor unui
formular interactiv sau coordonatelor unei zone senzitive (image map). CGI conferinter-
activitate paginilor Web, documentele HTML putnd astfel s-i modifice n mod dina-
mic coninutul i spermitprelucrri sofisticate de date. Programele CGI pot oferi su-
port de asemenea la autentificarea utilizatorilor pe partea server.
Regulile care trebuie respectate la conceperea unui scriptCGI sunt urmtoarele:
programul scrie datele (marcaje HTML, XML, imagini etc.) spre a fi tri-mise navigatorului Web la ieirea standard (stdout);
programul genereaz antete care permit serverului Web s interpretezecorect ieirea script-ului (folosindu-se specificaiile protocolului HTTP).
Cele mai multe script-uri CGI sunt concepute pentru a procesa datele introduse n for-
mulare. Un formular se definete n XHTML folosindu-se marcatori specifici pentru afi-
area coninutului i introducerea datelor de ctre client, iar script-ul, invocat i executat deserverul Web, va prelua coninutul acelui formular i-l va prelucra, returnnd, eventual,
rezultatele ctre navigator.
Antetul trimis serverului de ctre programul CGI va respecta specificaiile MIME, con-
innd de exemplu Content-type: text/html (document HTML sau XHTML) sau
Content-type: image/jpeg(imagine JPEG) ori Content-type: text/plain(text
obinuit).
Programului CGI i se vor transmite n diverse variabile de mediu sau de la intrarea
standard informaii referitoare la datele de procesat sau privitoare la clientul care a ini iat
cererea, n funcie de metoda de transfer utilizat.
Pentru a fi efective, programele CGI trebuie apelate (implicit sau explicit) din cadrul
paginilor Web. Uzual, un scriptCGI va fi invocat din cadrul unui formular HTML la ap-
sarea butonului de trimitere a datelor ctre server (butonul de
tip submit).
Spresupunem cavem urmtorul exemplu n care un utilizator introduce prin inter-
mediul unui formular dounumere ntregi, iar programul CGI va genera o paginWebconinnd maximul dintre ele.
-
7/22/2019 Program Are Perl
47/70
47
Formularul XHTML ar putea fi:
Vrugm, introducei dounumere:
De exemplu, introducnd numerele 7 i 4 i acionnd butonul etichetat "Aflmaxi-
mul", vom primi o paginWeb (un document marcat n XHTML) care va afia textul
"Maximul dintre 7 i 4 este numrul 7" (vezi figura).
Presupunnd cn cele doucmpuri ale formularului (purtnd numele nr1i respectivnr2) am introdus valorile 7 i 4 respectiv i am apsat butonul de tip submit(etichetat cu
"Aflmaximul"), navigatorul va trimite, prin intermediul protocolului HTTP, o cerere
ctre serverul Web aflat la adresa dat de URL-ul http://www.infoiasi.ro (adresa
este preluatdin valoarea atributului actional elementului ; script-ul poate fi lo-
calizat desigur i prin intermediul unui URL relativ). Desigur, n loc de o adresabsolut,
putea fi specificato cale relativ, nsemnnd faptul c se folosete serverul pe care se
gsete pagina coninnd formularul.
Atunci cnd se trimite cererea HTTP, navigatorul construiete un URL avnd ca sufixinformaii despre datele introduse n cmpurile formularului, n cazul nostru
http://www.infoiasi.ro/cgi-bin/max.cgi?nr1=7&nr2=4 folosindu-se o codificare
special. Pentru fiecare cmp al formularului, se va genera o pereche nu-
me_de_cmp=valoaredelimitatde caracterul "&", iar caracterele speciale (ca de exem-
plu slash-ul sau apostroful) vor fi nlocuite de codul lor numeric, n hexazecimal, precedat
de caracterul procent ("%"). Spaiile vor fi substituite de semnul plus ("+"). De exemplu,
pentru a trimite textul Cina de la Maxim'sse va folosi codificarea Cina+de+la+Maxim%27s.
-
7/22/2019 Program Are Perl
48/70
48
Introducerea datelor n formular i obinerea rezultatului furnizat
de script-ul CGI dupacionarea butonului de tip submit
Serverul spre care cererea a fost expediat(n cazul sitului www.infoiasi.roun ser-
verApacherulnd pe un sistem Linux) va procesa datele recepionate conform regulilorproprii. Tipic, configuraia serverului definete unde sunt stocate n cadrul sistemului de
fiiere directoarele i fiierele CGI. Fiierele de configurare a serverului n mod uzual se
regsesc n directorul /etc/httpd/conf/ .
De cele mai multe ori, daemonulHTTP (adicserverul Web, regsit ca proces de fundal
sub numele httpd) ruleazpe mainsub auspicii de utilizator fictiv (din raiuni de secu-
ritate ca nobodysau apache, n mod uzual), fiierele sale fiind stocate (n cazul unui sistem
UNIX/Linux) de obicei n directorul /var/www/. Aici, alturi de directorul html ori
public_html unde se memoreazdocumentele (HTML, CSS, fiiere multimedia, fiiereJavaScript etc.) unui sit Web, se afli directorul cgi-binunde ar trebui sfie stocate
toate fiierele (script-urile) CGI apelate din cadrul paginilor Web.
Aadar URI-ul http://www.infoiasi.ro/cgi-bin/max.cgi va nsemna pentru
serverul Web aflat la adresa www.infoiasi.ro urmtoarea aciune: "invoc programul
max.cgiaflat la /home/httpd/cgi-bin". Astfel, n loc strimitctre navigatorul Web
care a iniiat cererea HTTP un document HTML sau un fiier de alt tip, serverul va invoca
script-ul CGI specificat (n acest caz max.cgi) i-i va pasa datele furnizate de sufix, de
dupsemnul ntrebrii (adicirul nr1=7&nr2=4).
-
7/22/2019 Program Are Perl
49/70
49
Aciunea de invocareva avea o semanticdiferit n funcie de script-ul CGI conceput.
Pentru un scriptPerl, serverul va invoca un interpretor Perl (n cazul Apache, un modul
special mod_perl; de fapt, pentru a permite execuia de programe CGI, serverul Apache
se va folosi de serviciile modulului mod_cgi).
Procesul de invocare a unui scriptCGI
Extensia de fiier .cginu are nici o relevann general, dar pot exista diverse reguli
de numire a fiierelor CGI executabile dependente de server sau de sistemul de operare
pe care ruleaz. Pentru ca un scriptCGI spoatfi invocat trebuie spoatfi citit i exe-
cutat de utilizatorul fictiv sub care i desfoaractivitatea serverul Web.
n funcie de metoda de transfer folosit, script-ul CGI va primi n mod diferit irul de
interogare.
Pentru metoda GET (metoda implicitde transfer a datelor de la un na-vigator Web), informaiile din irul de interogare (cele de dupdelimitatorul "?")
vor fi disponibile ntr-o variabilde mediu purtnd numele QUERY_STRING. Ast-
fel, n cazul exemplului de mai sus valoarea acestei variabile va fi nr1=7&nr2=4).
Metoda POST este util n situaiile n care avem de trimisscript-ului CGI spre prelucrare un volum mai mare de date (de exemplu, coninu-tul unei scrisori ori al unui fiier) sau informaii confideniale
(e.g.parole) care nu trebuie saparn componena URI-ului transmis serverului
Web.
Pentru formularele utiliznd metoda POST, datele pasate script-ului vor putea fi
accesate de la intrarea standard (stdin), iar lungimea, n octei,
a informaiilor trimise va fi disponibiln variabila de mediu CONTENT_LENGTH .
De multe ori este util ca ntr-un scriptCGI sdetectm metoda de transfer pentru a
prelua datele n mod corespunztor. Pentru aceasta va trebui sse testeze valoarea varia-bilei de mediu REQUEST_METHOD .
-
7/22/2019 Program Are Perl
50/70
50
Dupcum am vzut mai sus, nainte de a trimite spre navigator pagini Web sau alte ti-
puri de informaii (multimedia, arhive, documente XML etc.), orice scriptCGI trebuie s
afieze la ieirea standard cmpul HTTP Content-type.
Desigur, nici script-urile CGI concepute n Perl nu fac excepie. Astfel, cel mai simpluscripteste urmtorul:
#!/usr/bin/perl
# trimitem antetul HTTP
print "Content-type: text/html\n\n";
# trimitem codul HTML,
# (folosim facilitatea "here")
print
-
7/22/2019 Program Are Perl
51/70
51
Preluarea datelor prin metoda GET
Pentru a accesa datele transmise prin intermediul metodei GET va trebui sle prelumca URI codificat din variabila de mediu QUERY_STRING.
Ne propunem s scriem un scriptPerl simplu care preia dintr-un formular valorile a
dounumere ntregi i returneazclientului Web maximul dintre cele numere. Vom scrie
aadar urmtorul formular XHTML:
Introduceti dounumere:
De exemplu, introducnd numerele 3 i 1 i acionnd butonul "Aflmaximul", vom
primi o paginWeb care va afia textul "Maximul dintre 3 i 33 este: 33".
Script-ul Perl va prelua din variabila de mediu QUERY_STRINGirul de interogare codi-
ficat:
$interogare = $ENV{'QUERY_STRING'};
Va trebui sdivizm acest ir de caractere n perechi (nume de cmp, valoare) i apoi s
prelum valorile fiecrui cmp al formularului. Acest lucru se realizeazn maniera urm-
toare, implementnd funcia analiza_parametri()care va returna un tablou asociativ
avnd drept chei numele cmpurilor i ca valori valorile acestor cmpuri:
sub analiza_parametri {
# variabile localelocal($interogare) = @_;
# preluam perechi 'camp=valoare'
local(@perechi) = split('&', $interogare);
local($parametru, $valoare, %parametri);
foreach (@perechi) {
# preluam valoarea si numele de camp
($parametru, $valoare) = split('=');
# decodificam valorile
$parametru = &unescape($parametru);$value = &unescape($value);
-
7/22/2019 Program Are Perl
52/70
52
# memoram in tabloul 'parametri'
if ($parametri{$parametru}) {
$parametri{$parametru} .= "$;$valoare";
} else {
$parametri{$parametru} = $valoare;}
}
return %parametri;
}
Mai rmne sdecodificm irurile de caractere ("+" va deveni spaiu, iar "%" urmat de
doucifre n baza 16 va fi substituit de caracterul ASCII corespunztor):
sub unescape {
local($sir) = @_;
# "+" devine spatiu
$sir =~ tr/+/ /;
# %HH devine caracter ASCII
$sir =~ s/%([0-9A-Fa-f]{2})/pack("c", hex($1))/ge;
return $sir;
}
Script-ul complet max.pl.cgieste urmtorul:
#!/usr/bin/perl -w
# calculeaza maximul a doua numere
# (se utilizeaza metoda GET)
print
-
7/22/2019 Program Are Perl
53/70
53
else {
$max = $nr2;
}
print "
Maximul dintre $nr1 si $nr2 este: $max
\n";print -
7/22/2019 Program Are Perl
54/70
54
Preluarea datelor prin metoda POST
Trimind valorile cmpurilor formularului prin metoda POST, nu vom mai consulta
variabila de mediu QUERY_STRING, ci vom citi de la intrarea standard CONTENT_LENGTHoctei care, desigur, vor trebui decodificai. Pentru decodificare vom folosi rutinele pre-
zentate mai sus, codul script-ului fiind (rutinele analiza_parametri() i unescape()
au fost omise):
#!/usr/bin/perl -w
# calculeaza maximul a doua numere
# (se utilizeaza metoda POST)
print
-
7/22/2019 Program Are Perl
55/70
55
;
# am terminat
exit;
-
7/22/2019 Program Are Perl
56/70
56
2.2 Modulul CGI
Pentru realizarea comodde script-uri CGI n Perl, este pus la dispoziie modulul CGI,
utilizat n special pentru generarea i procesarea formularelor i a cookie-urilor. Acest mo-dul oferun obiect generic CGIpentru acces la variabile de mediu, pentru procesarea lor
i stocarea rezultatelor. Modulul CGI poate fi utilizat pentru preluarea datelor transmise
att prin metoda GET, ct i prin metoda POST, fra concepe programe separate pen-
tru fiecare metodn parte. Un alt avantaj este dat de posibilitatea de a depana script-urile
CGI rulndu-le direct de laprompt-ul Linux, n loc de a fi invocat prin intermediul serve-
rului Web.
Modaliti de utilizare
Putem folosi modulul CGI prin intermediul a douparadigme de programare:funciona-
l(procedural) i obiectual.
Cele douparadigme nu diferdect prin modul de acces la funcionalitile modulu-
lui: via funcii n primul caz i via metode n al doilea.
Urmtorul exemplu folosete paradigma procedural:
#!/usr/bin/perl
# utilizam modulul CGI in forma standard
use CGI qw/:standard/;
# trimitem antetul HTTP
print header();
# afisam antetul paginii Web
print start_html(-title => "Un salut");
# afisam diferite elemente HTML
print h1('Salut!'),
p('Un paragraf...');# afisam finalul de document
print end_html();
Acelai script, din perspectiva orientat-obiect, este:
#!/usr/bin/perl
# utilizam modulul CGI
use CGI;
# instantiem obiectul CGI$c = new CGI;
-
7/22/2019 Program Are Perl
57/70
57
# trimitem antetul HTTP
print $c->header();
# afisam antetul paginii Web
print $c->start_html(-title => "Un salut");
# afisam diferite elemente HTMLprint $c->h1('Salut!'),
$c->p('Un paragraf...');
# afisam finalul de document
print $c->end_html();
Preluarea parametrilor
Cele mai uzuale utilizri ale modulului CGI sunt cele n care sunt implicate formularele
Web ale cror valori de cmpuri trebuie prelucrate comod.
Pentru a prelua toi parametrii pasai script-ului ne putem sluji de un tablou, apelnd
metoda param():
@parametri = $c->param;
Dacdorim s prelum valoarea unui anumit parametru vom folosi una dintre con-
struciile:
@prieteni = $c->param('prieteni');
$culoare = $c->param('culoare');
n prima variant, rezultatul este preluat de un tablou, deoarece cmpul prieteni
poate conine elemente multiple ale unui marcator .
Varianta proceduraleste:
$o_culoare = param('culoare');
Atunci cnd dorim s asignm o nou valoare unui parametru, vom scrie,
de exemplu:
$c->param(-name=>'culoare', -value=>'rosu');
Procesarea antetului HTTP
Aa cum am vzut, nainte de a genera cod-sursHTML, un scriptCGI trebuie strimi-
tobligatoriu antetul HTTP. Acest lucru se realizeazprin intermediul metodei sau func-
iei header():
# trimite Content-type: image/gif
print $c->header('image/gif');
Metoda header()poate fi folositi pentru a seta alte cmpuri HTTP:
-
7/22/2019 Program Are Perl
58/70
58
print $c->header(
# Content-type
-type => 'image/png',
# codul de stare HTTP
-status => '402 Payment Required',# timpul de expirare
-expires => '+3d',
# parametru-utilizator
-Cost => '$ 0.01');
Pentru atributul -expirespot fi specificate valori de timp precum now(acum), +30s
(dup30 de secunde), +15m (dup15 minute), +5h(dup5 ore) sau +3M (dup3 luni).
Sunt acceptate i valori negative.
Pot fi, de asemenea, trimise cmpuri definite de utilizatori, n exemplul de mai susCost. Acest lucru permite folosirea unor protocoale noi, fra trebui sactualizm mo-
dulul CGI.
Mai mult, se poate folosi metoda redirect()pentru a redirecta navigatorul ctre alt
locaie:
# redirectare in functie de limba
if ($limba eq 'ro')
print $c->redirect('/ro/index.html');
else
print $c->redirect('/en/index.html');
De asemenea, se pot invoca diverse metode care sofere valorile variabilelor de mediu
specifice HTTP. Astfel, putem apela metode precum:
query_stringreturneazirul de interogare CGI; remote_addr() furnizeaz adresa IP a calculatorului client care a
invocat script-ul;
remote_host()ca mai sus, dar se returneaznumele simbolic al calculatoruluiclient;
request_method() furnizeaz metoda HTTP utilizat (GET, POSTsau HEAD);
user_agent() identificnumele i versiunea agentului-utilizator (navigatorului,de cele mai multe ori) folosit pe calculatorul client.
Iatun exemplu n care redirectm automat browserul, n funcie de sistemul de opera-
re al clientului:
#!/usr/bin/perl
-
7/22/2019 Program Are Perl
59/70
59
use CGI;
$url = 'http://www.infoiasi.ro';
for (CGI::user_agent()) {
# simularea unui 'switch'$pag = /Linux/ && 'linux.html'
|| /HP-UX/ && 'hpux.html'
|| /SunOS/ && 'sunos.html'
|| /Mac/ && 'macos.html'
|| /Win|MSIE/ && 'win.html'
|| /.*/ && 'generic.html';
}
print "Location: $url/$pag\n\n";
n loc de user_agent()puteam folosi $ENV{HTTP_USER_AGENT} , desigur.
Alte funcii utile oferite de modulul CGI sunt:
escape()convertete un ir de caractere n codificarea utilizatde URI-urile CGI;
unescape() convertete un ir codificat CGI n reprezentareasa normal;
use CGI qw/escape unescape/;
$sir = escape('~/:#?');
print unescape($sir);
escapeHTML()convertete un ir de caractere, substituind orice caracterHTML ilegal prin entitatea corespunztoare;
unescapeHTML() convertete un ir de caractere coninnd entitiHTML n ir obinuit.
use CGI qw/escapeHTML unescapeHTML/;
$sir = escapeHTML('Un sir mai ...');
print unescapeHTML($sir);
-
7/22/2019 Program Are Perl
60/70
60
Modulele CGI
n fapt, modulul CGI este suplinit i de urmtoarele module:
Base.pm ofer funcionalitile de baz pentru dezvoltarea de script-uriCGI;
BasePlus.pm extinde modulul precedent, adugnd faciliti precumuploadde fiiere;
Request.pmeste responsabil cu analiza i procesarea cererilor HTTP; Form.pmeste folosit pentru a genera mai uor formulare Web, n loc de a
scrie cod HTML;
MiniSvr.pmimplementeazun server HTTP minimal; Response.pmeste utilizat pentru a genera antete HTTP; Carp.pmpermite redirectarea mesajelor de eroare ctre navigator, spre un
fiier jurnal sau un fiier utilizator.
De menionat aici i faptul cserverul Apache incorporeazdirect interpretorul Perlprin intermediul modulului mod_perl, astfel nct timpul de execuie a script-urilor CGI
concepute n Perl sfie minim. Pentru fiecare scriptPerl invocat, serverul Web va lansa o
nou instana interpretorului implementat de mod_perl. De asemenea, la iniializarea
serverului (pornirea daemonuluihttpd) putem configura mod_perlastfel nct sse ncar-
ce modulele Perl dorite n acest moment i nu la prima lor utilizare, accelerndu-se timpul
de execuie a script-urilor.
-
7/22/2019 Program Are Perl
61/70
61
2.3 Exemple de script-uri
Furnizm n continuare o serie de exemple de script-uri CGI, folosind sau nu modululCGI.
Calendar
ncepem cu un exemplu clasic al unui scriptcare afieazcalendarul unui an (furnizat de
utilizator sau anul curent). Pentru generarea calendarului se va recurge la comanda UNIX
cal. Acest script nu folosete modulul CGI i poate fi invocat indiferent de metoda
HTTP utilizat(pentru aceasta vom testa valoarea variabilei de mediu REQUEST_METHOD).
#!/usr/bin/perl -w
# afiseaza calendarul,
# folosind comanda UNIX 'cal'
# (scriptul va fi functional indiferent
# de metoda HTTP folosita: GET sau POST)
$CAL = '/usr/bin/cal';
@ani = (1990..2033);
%interogare = &furnizeaza_interogarea;
# preluam anul
if ($interogare{'an'}) {
$an = $interogare{'an'};
} else {
chop($an = `date +%Y`);
}
# antetul paginii
print
-
7/22/2019 Program Are Perl
62/70
62
print "$un_an\n";
}
print "\n";
# butonul de trimitere
print '
';
print "\n\n";
# ne pregatim de afisarea calendarului
# verificam anul
unless ($an=~/^\d{4}$/) {print "
Anul trebuie sa aiba 4 cifre
\n";exit 0;
}
# executam comanda 'cal' pasindu-i ca parametru anul dorit
chop($calendarul = `$CAL $an`);
# rezultatul returnat de 'cal'
# este afisat preformatat cu
print
-
7/22/2019 Program Are Perl
63/70
63
# iesim, daca nu e furnizata nici o data
return () unless $interogarea;
# procesam interogarea
return &analiza_parametri($interogarea);
}
sub analiza_parametri {
# variabile locale
local($interogare) = @_;
# preluam perechi 'camp=valoare'
local(@perechi) = split('&', $interogare);
local($parametru, $valoare, %parametri);
foreach (@perechi) {
# preluam valoarea si nu