program are perl

Upload: ady-andyy

Post on 10-Feb-2018

219 views

Category:

Documents


0 download

TRANSCRIPT

  • 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