Creat initial pentru accesarea si prelucrarea textelor mari si 12212h719m foarte mari, Perl este astazi un limbaj matur cu multe domenii de aplicabilitate. Deviza limbajului? "Întotdeauna exista mai multe solutii de rezolvare"
Perl este unul dintre limbajele de programare la moda care a cunoscut o dezvoltare rapida si o extindere ampla a domeniilor de aplicatie. Larry Wall este numele celui care a initiat dezvoltarea acestui limbaj. De-a lungul anilor si-au adus contributia însa multi programatori la ceea ce este Perl astazi.
O prezentare a limbajului Perl arata ca a fost initial creat pentru accesarea si prelucrarea textelor mari si 12212h719m foarte mari, pentru crearea si obtinerea dinamica de date si pentru realizarea de rapoarte pe baza acestor date [1]. Limbajul ofera unul dintre cele mai puternice mecanisme (daca nu cel mai puternic) de manipulare a textelor, de pattern matching si mai ales de utilizare a expresiilor regulate. Dar în prezent Perl este mult mai mult decât atât, putând fi considerat un limbaj complet. Este un limbaj pentru manipularea fisierelor, managementul proceselor, administrarea bazelor de date, aplicatii client-server, managementul informatiilor de pe Web, programarea CGI (Common Gateway Interface), aplicatiile din domeniul programarii orientate obiect si functionale, etc. Este popular în special printre programatorii/administratorii de sistem si de aplicatii Web [3, 4, 5].
Perl a fost creat pentru mediul UNIX, dar în prezent ruleaza în aproape toate sistemele de operare: MS-DOS, VMS, OS/2, Machintosh, toate versiunile de Windows, etc. Programatorii UNIX au avut o mare contributie la dezvoltarea limbajului, ceea ce poate fi usor observat prin faptul ca au încercat sa pastreze cât mai multe din facilitatile oferite de mediile UNIX. Perl mosteneste beneficiile oferite de limbajul C si programarea shell, având si un superset de facilitati din awk si sed.
Deviza limbajului este TMTOWTDI, adica "There's More Than One Way To Do It". Exista mai multe moduri în care pot fi rezolvate problemele în Perl, moduri care depind în special de nivelul de cunoastere a limbajului.
Perl poate fi considerat simplu si bogat în acelasi timp. Este un limbaj simplu pentru ca lucrurile simple sunt simplu de rezolvat folosind Perl, pe când lucrurile complicate devin posibile de implementat. Lucrurile simple sunt cele care trebuie rezolvate zi de zi, care implica manipularea numerelor si textelor, fisierelor si directoarelor, calculatoarelor si retelelor, dar mai ales a programelor. Programele trebuie sa fie usor de dezvoltat, manipulat si depanat. si nu numai: trebuie sa fie portabile. Perl poseda toate aceste caracteristici si înca multe altele.
Perl nu ofera un interpretor în sensul clasic [1], care compileaza si executa o singura comanda la un moment dat. Perl compileaza initial tot programul într-un format intermediar, facând în acelasi timp diferite optimizari si furnizând erorile sintactice si semantice. Daca nu apare nici o eroare la compilarea programului, atunci codul intermediar este transmis interpretorului pentru executie. Toate aceste amanunte par a fi complicate, dar, atât compilatorul, cât si interpretorul, sunt foarte eficiente si tot ciclul compileaza-executa-modifica se poate masura în secunde.
Perl este un limbaj simplu de învatat si utilizat, dar care ofera mecanisme puternice si eficiente. Este un limbaj cu ajutorul caruia orice programator îsi poate rezolva problemele din domeniul profesional, evident. Este un limbaj care stimuleaza creativitatea programatorului prin libertatea de exprimare pe care o ofera.
Articolul de fata îsi propune o prezentare sumara a câtorva din caracteristicile si facilitatile oferite de Perl, fiind doar o introducere modesta în mecanismele de prelucrare ale limbajului. Scopul principal este de a va face cunoscut ca acest limbaj exista si ca poate fi utilizat eficient pentru implementarea diferitelor aplicatii software. Articolul contine totodata si o scurta descriere a expresiilor regulate care constituie cheia instrumentelor de prelucrare a textelor în Perl.
Caracteristici ale limbajului
Dintre caracteristicile importante ale limbajului Perl [2, 5] putem aminti:
- Modularitatea - limbajul permite proiectarea, programarea si depanarea rapida a aplicatiilor, dar si extinderea functionalitatii acestor aplicatii conform cerintelor care se ivesc; Perl poate fi încorporat în aplicatiile din alte limbaje de programare, precum poate încorpora la rândul sau cod scris în alte limbaje.
- Viteza de dezvoltare a programelor - în Perl programele se pot scrie folosind orice editor de texte; nu este necesar un compilator separat; ciclul compileaza-executa-modifica este mult mai scurt.
- Puterea limbajului - asa cum s-a precizat anterior, Perl ofera unul dintre cele mai puternice mecanisme de lucru cu expresii regulate; ofera facilitati pentru lucrul cu obiecte si socketi, baze de date, etc.
- Portabilitatea - programele scrise în Perl pot fi executate fara nici o modificare atât în sistemele de operare UNIX, cât si în orice versiune de Windows sau alt sistem de operare.
- Mediul de dezvoltare - orice editor de texte este suficient pentru dezvoltarea de aplicatii Perl; programele pot fi scrise în joe, vi sau Notepad, Word 97.
- Pretul - într-adevar Perl este ... nepretuit; poate fi procurat si utilizat liber.
Un prim program
Traditia ar spune ca un prim program sa constea în afisarea mesajului "Hello World!", însa experienta spune ca un program mai interesant, care sa scoata în evidenta simplitatea si totodata puterea limbajului Perl, ar stârni repede si definitiv interesul cititorilor.
Enuntul unui prim program este de asemenea foarte simplu. Rezultatele unui examen sunt stocate într-un fisier. Examenul are trei probe: scris, oral si proba practica. În fisier apar doua coloane: prima contine numele studentului, iar a doua coloana, nota obtinuta la una din cele trei probe. Cele doua coloane sunt despartite de ":". Numele unui student poate apare de mai multe ori în fisier, în functie de câte probe a sustinut. Cerinta problemei este de a afisa pentru fiecare student numele si nota finala. Studentii vor fi afisati în ordinea descrescatoare a notei finale. (vezi Listing 1)
Dupa cum se poate lesne observa, programul este usor de înteles, în special pentru programatorii de C sau shell. Numerele de la începutul fiecarei linii nu au nici o legatura cu programul, fiind însa utile pentru comentarea acestuia. Deci nu folositi aceste numere la scrierea programelor în Perl!
Fiecare program scris în Perl începe cu linia:
#!/usr/local/bin/perl
care poate diferi în functie de calea în care se afla executabilul limbajului Perl. Aceasta linie specifica faptul ca fisierul trebuie executat ca un program Perl.
Linia numarul 5 din program încearca sa deschida fisierul care contine datele de intrare pentru citire. Aceasta linie se compune de fapt din doua instructiuni legate printr-un sau logic: or. În cazul în care fisierul de intrare este deschis pentru citire, cea de a doua instructiune nu se mai executa. În caz contrar, se executa cea de-a doua instructiune care se termina întotdeauna cu succes, în sensul ca, executia programului este oprita, afisându-se mesajul indicat împreuna cu tipul erorii stocat într-una din variabilele speciale ale Perl-ului: $!.
Trebuie mentionat ca, limbajul Perl dispune de o serie întreaga de variabile speciale care la prima vedere ar conduce la o întelegere mai dificila a programelor, dar care de fapt ajuta foarte mult programatorii la reducerea dimensiunii programelor si la cresterea eficientei acestora.
Liniile 7-13 contin instructiunile necesare pentru citirea linie cu linie a datelor din fisier si stocarea lor într-o tabela hash. O tabela hash este un sir ale carui elemente sunt accesate dupa chei si nu dupa numere sau dupa un index ca la sirurile obisnuite. În cazul de fata, numele studentilor reprezinta cheile tabelei, iar notele reprezinta valorile sale. Notele sunt memorate toate într-un singur string, fiind despartite de câte un spatiu. Deci notele asociate fiecarui student pot fi accesate utilizând cheia studentului, adica numele sau.
Fisierul de intrare este închis (în linia numarul 15) o data ce toate datele de intrare au fost memorate în tabela hash.
Parcurgerea unei tabele hash se poate face dupa cheile sau valorile sale. Linia numarul 17 indica modul în care se parcurge tabela dupa chei, adica dupa numele studentilor.
Pentru a calcula nota finala a fiecarui student, trebuie calculata media notelor obtinute la probele sustinute. Deoarece notele studentilor sunt memorate într-un string, se face conversia stringului la un sir, în care fiecare element al sirului reprezinta o nota (linia numarul 21). Linia numarul 21 reprezinta oarecum operatia inversa celei de la numarul 12.
Pentru afisarea rezultatelor trebuie facuta ordonarea descrescatoare a studentilor în functie de nota finala. Aceasta operatie este realizata de continutul parantezei rotunde din linia 35. Functia sort primeste doi parametrii: o functie dupa care se face sortarea si un sir care trebuie sortat. sirul specificat ca parametru în linia 35 reprezinta de fapt un sir format din numele studentilor.
Liniile 30-33 contin definitia subrutinei, care poate fi considerata o functie sau o procedura, ce compara doua elemente întorcând un întreg, adica rezultatul functiei cmp. Nu sunt direct comparate valorile $a si $b deoarece acestea reprezinta doua elemente ale sirului ce trebuie sortat, adica doua nume de studenti, si nu notele lor, pe când cerinta problemei este de a ordona studentii în functie de notele obtinute. În Perl nu se face distinctie între functii si proceduri, existând doar subrutine.
Pentru a executa acest program în UNIX, trebuie ca fisierul în care este stocat sa aiba drepturi de executie. Programul se poate executa prin simpla comanda:
perl [optiuni] nume_program lista_argumente
Optiunile sunt utilizate pentru obtinerea de informatii suplimentare în timpul compilarii/interpretarii programului sau pentru specificarea modului în care se doreste efectuarea compilarii/interpretarii sau executiei programului (de exemplu, optiunea -c verifica corectitudinea programului din punct de vedere sintactic, fara a-l executa).
Ca si în C sau Java, se pot specifica argumentele transmise programului în linia de comanda prin lista_argumente.
Daca programul contine erori, acestea pot fi sau nu afisate pe ecran. Pentru a vizualiza mesajele de eroare, de atentionare sau orice alt tip de mesaj util pentru înlaturarea erorilor, se foloseste optiunea "-w":
perl -w nume_program
sau se adauga la prima linie de program:
usr/local/bin/perl -w
Pentru a rula programul pentru depanare, se utilizeaza optiunea "-d". Toate celelalte optiuni pot fi descoperite prin comanda man perlrun.
Când este lansata comanda pentru executia programului, Perl compileaza mai întâi tot programul dupa care executa versiunea compilata.
Comentariile pot fi introduse oriunde în program. Orice comentariu începe cu caracterul "#" (exceptând prima linie din program) si se termina la sfarsitul liniei care contine "#". O alta modalitate de introducere a comentariilor în programe este utilizarea unei linii care începe cu semnul egal urmat imediat de o litera. Sfârsitul comentariului este indicat de semnul egal urmat de cuvântul "cut", aflate la inceputul unei linii urmatoare. Tot ceea ce se afla între cele doua linii care încep cu semnul egal, este considerat comentariu.
=Comentariu!
Acesta este un exemplu de comentariu în Perl!
=cut
care este echivalent cu :
#Comentariu!
#Acesta este un exemplu de comentariu în Perl!
Atentie: Perl este case sensitive, adica $var si $Var reprezinta doua variabile diferite.
Trei observatii
- O observatie importanta este aceea ca programul prezentat în listing 1 nu contine nici o declaratie de tip. Toate variabilele sunt folosite direct, fara a fi nevoie sa fie declarate anterior. În schimb, fiecare variabila este precedata de unul din caracterele $, @, %, care indica implicit tipul variabilelor, adica scalar, sir si respectiv, tabele hash sau array-uri asociative. Acest lucru permite citirea si întelegerea usoara a programului, nefiind necesara defilarea întregului program pentru a gasi locul de declaratie a variabilei respective si a-i afla tipul.
- În Perl nu exista notiunea de cast, adica conversia explicita de tip. Conversia de tip se face automat (de exemplu, conversia numerelor în stringuri). Un exemplu care sustine afirmatia anterioara este linia numarul 11 din programul prezentat. Elementele unui sir sunt stocate într-un string, fiind despartite de câte un spatiu. Daca sirul are doua elemente:
$nume_student[0] este "Ion"
$nume_student[1] este "Ionescu"
atunci
$nume_final este "Ion Ionescu"
În cazul în care s-ar renunta la "" si instructiunea ar deveni:
$nume_final = @nume_student;
rezultatul ar fi cu totul altul (în variabila scalara $nume_final s-ar memora lungimea array-ului @nume_student). Acest lucru se datoreaza schimbarii de context, pentru ca în Perl totul se evalueaza în functie de contextul existent.
- Alocarea si dealocare variabilelor este de asemenea facuta în mod automat. Nu este nevoie de specificarea numarului de elemente ale unui sir si nici de alocarea sau dealocarea spatiului corespunzator. În C, programatorul trebuie sa aiba grija de alocarea si dealocarea variabilelor, pe când în Java este necesara doar alocarea spatiului corespunzator, deoarece are implementat mecanismul de garbage collector. Însa Perl rezolva automat ambele probleme. De exemplu, poate memora într-un singur string continutul unui întreg fisier, daca evident exista memoria necesara, aspect ce nu tine de limbaj. Speram ca a câstigat deja simpatia multor programatori prin aceasta caracteristica importanta.
Expresii regulate în Perl
Mecanismele de manipulare a textelor reprezinta una dintre cele mai importante si puternice facilitati oferite de limbajul Perl, expresiile regulate constituind nucleul acestor mecanisme. Expresiile regulate sunt folosite în special în programe si aplicatii UNIX: grep, sed, awk, vi, emacs, si nu numai.
Dar ce este o expresie regulata? O expresie regulata este considerata o gramatica regulata pentru un limbaj. Interpretorul de expresii regulate compara gramatica cu sirul de caractere în care se face cautarea. Daca o parte din sirul de cautare poate fi considerat ca fiind o propozitie ce apartine limbajului, atunci interpretorul va întoarce ca rezultat valoarea de adevar, altfel valoarea de fals.
Ceea ce se întâmpla dupa ce interpretorul gaseste o propozitie care satisface expresia regulata depinde de scopul cautarii expresiei regulate:
- determinarea existentei unui sir de caractere care satisface expresia regulata; în acest caz rezultatul va fi o valoare booleana: adevarat sau fals; în general aceste expresii regulate apar în instructiuni conditionale;
- substituirea sirului de caractere care satisface expresia regulata cu un alt string specificat de programator; în acest caz rezultatul va fi un numar întreg pozitiv, care reprezinta numarul de substitutii efectuate;
- divizarea unui sir de caractere dupa expresia regulata; rezultatul va fi reprezentat de o lista a partilor sirului de cautat care nu satisfac expresia regulata (expresia regulata joaca în acest caz un rol de delimitator pentru partile din string care nu satisfac expresia regulata).
Pattern matching
Cazul cel mai simplu în care sunt utilizate expresiile regulate este pattern matching, adica determinarea existentei unui sir de caractere care satisface expresia regulata. Un exemplu de aplicatie pattern matching este: sa se afiseze toate liniile dintr-un fisier HTML care contin link-uri catre alte pagini HTML. Orice astfel de link care apare într-un fisier HTML începe cu "https:". Este suficient sa se parcurga fisierul linie cu linie si sa se verifice existenta stringului "https:" în fiecare linie:
while ( $linie = <FIS_HTML> )
Operatorul =~ se numeste pattern-binding. Este un operator infixat care leaga stringul de cautare cu expresia regulata de cautat. Expresia regulata este de obicei delimitata de slash-uri. În cazul în care operatorul =~ nu apare în instructiunea if, fiind specificata doar expresia regulata de cautat /http , Perl considera variabila speciala $_ ca variabila implicita de cautare. $_ este variabila implicita si pentru <>, operatorul de citire din fisier. Astfel secventa anterioara devine:
while ( <FIS_HTML> )
Daca se doreste afisarea tuturor liniilor din fisierul HTML care contin orice tip de link atunci secventa corespunzatoare de cod este:
while ( <FIS_HTML> )
Parantezele patrate definesc o clasa de caractere, în acest caz clasa tuturor literelor din alfabet. Semnul plus are urmatoarea semnificatie: "una sau mai multe aparitii a ceea ce este în fata mea" (adica una sau mai multe litere pentru exemplul prezentat). Deci, în acest caz, orice tip de link (http hTtP:, mailto:, ftp:, FTP:) este descris de expresia regulata din exemplul anterior.
Exista patru variabile speciale asociate expresiilor regulate: $+, $&, $`, $'.
$+ contine stringul care corespunde utimei paranteze evaluate din expresia regulata
$& contine întregul string care corespunde expresiei regulate
$` contine tot ceea ce este înaintea stringului corespunzator expresiei regulate
$' contine tot ceea ce urmeaza stringului corespunzator expresiei regulate
[email protected]. Astept mail.';
\w+)\@(.*?)\s/;
print "Ultima paranteza evaluata din expresia regulata: $+.\n";
print "Ce este înaintea expresiei regulate: $`.\n";
print "Expresia regulata: $&.\n";
print "Ce este dupa expresia regulata: $'.\n";
Variabilele speciale vor avea urmatoarele valori în urma executiei acestei secvente de cod:
$+ : athena.polito.it
$` : Adresa de e-mail este:
$& : [email protected].
$' : Astept mail.
Substitutia si traducerea
De cele mai multe ori nu este suficient un rezultat boolean care sa indice existenta sau inexistenta unei anumite expresii regulate în cadrul unui text sau al unei variabile, dorindu-se modificarea sau substituirea totala sau partiala a string-ului gasit.
Limbajul Perl ofera doua metode distincte pentru prelucrarea expresiei regulate identificate:
- substitutia - permite înlocuirea întregului sir de caractere care satisface expresia regulata cu un alt sir specificat de programator;
- traducerea - permite înlocuirea partiala sau chiar totala a sirului de caractere care satisface expresia regulata, substitutia facându-se caracter cu caracter.
Functia cu ajutorul careia se realizeaza substitutia în Perl se numeste "s". Atât expresia regulata de înlocuit, cât si expresia de înlocuire sunt încadrate de delimitatori.
$_ = "Piesa de teatru \"Azilul de noapte\" am vazut-o azi la matineu.";
$nr_de_inlocuiri = s/azi/ieri/ig;
print "Numarul de înlocuiri este: $nr_de_inlocuiri.\n";
Functia "s" substituie orice secventa de caractere care satisface expresia de cautat cu ceea ce se gaseste între al doilea si al treilea delimitator (în cazul de fata "ieri"). Numarul de înlocuiri afisat dupa executia acestei secvente de cod este 2 si nu 1, asa cum ar fi fost de asteptat.
Din punct de vedere semantic, în exemplul de mai sus se dorea schimbarea complementului de timp, însa substitutia se face pentru orice aparitie consecutiva a literelor "a", "z" si "i", indiferent daca ele formeaza un cuvânt separat sau fac parte din cadrul unui cuvânt. Secventa de cod corecta care satisface cerinta si din punct de vedere semantic este:
$_ = "Piesa de teatru \"Azilul de noapte\" am vazut-o azi la matineu.";
$nr_de_inlocuiri = s/\bazi\b/ieri/ig;
print "Numarul de înlocuiri este: $nr_de_inlocuiri.\n";
"\b" indica începutul sau sfârsitul unui cuvânt. Rezultatul afisat de aceasta data este 1, iar întelesul nou al frazei este cel dorit.
O aplicatie imediata a substitutiei este stergerea stringurilor care satisfac expresia regulata specificata. Aceasta se realizeaza prin inserarea în cadrul substitutiei a sirului vid ca expresie regulata de înlocuire:
$_ = "Piesa de teatru \"Azilul de noapte\" am vazut-o azi la matineu.";
$nr_de_inlocuiri = s/\bazi\b//ig;
print "Noul string este: $_ \n";
sirul sau sirurile de caractere care satisfac expresia regulata de cautat pot fi memorate în cadrul unui scalar sau în cadrul unei liste în functie de scopul urmarit:
$_ = "Piesa de teatru <I>Azilul de noapte</I> am vazut-o ieri la <I>Notara</I> in <I>Bucuresti</I>";
($prim, $secund) = /<I>(.*?)<\/I>/ig;
print "Primul element: $prim, al doilea element: $secund.\n";
($prim, @rest) = /<I>(.*?)<\/I>/ig;
print "Primul element: $prim, restul " . "@rest" . ".\n";
($prim, @sir, $ultim) = /<I>(.*?)<\/I>/ig;
print "Primul element: $prim; ultimul element $ultim \n";
@rezultat = /<I>(.*?)<\/I>/ig;
print "Rezultatul este: @rezultat.\n";
Exista posibilitatea de a memora separat elemente ale sirului întors ca rezultat, ca de exemplu $prim si $secund. Atentie însa ca variabila $ultim va ramâne nedefinita deoarece sirurile sunt lacome.
Numarul de siruri de caractere care satisfac expresia regulata de cautare se poate obtine în doua moduri diverse:
$_ = "Piesa de teatru <I>Azilul de noapte</I> am vazut-o ieri la <I>Notara</I> in <I>Bucuresti</I>";
$total++ while /<I>.*?<\/I>/ig;
print "Numarul de match-uri: $total.\n";
sau
$_ = "Piesa de teatru <I>Azilul de noapte</I> am vazut-o ieri la <I>Notara</I> in <I>Bucuresti</I>";
$total = s/<I>(.*?)<\/I>/<I>$1<\/I>/ig;
print "Numarul de match-uri: $total.\n";
Extinderi ale expresiilor regulate introduc noi facilitati care pot fi extrem de utile, de exemplu, în cadrul substitutiei. Substitutia unui anumit cuvânt poate fi conditionata de faptul ca el este urmat sau nu de un anumit caracter sau de un anumit cuvant. În acest caz este utila explorarea anticipata a frazei sau sirului de cautare fara însa ca acest ultim caracter sau cuvânt sa fie memorat în variabila $& (variabila care contine sirul de caractere corespunzator expresiei regulate de cautare).
(?= ...) permite indicarea caracterului sau cuvântului care urmeaza dupa stringul de cautare;
) permite indicarea caracterului sau cuvântului care nu trebuie sa urmeze stringului de cautare.
Un exemplu de aplicatie care foloseste aceste mecanisme este verificarea existentei semnului de punctuatie ";" la sfârsitul fiecarei linii de cod dintr-un program C, Java sau Perl. Evident este un exemplu trivial care nu ia în consideratie faptul ca pot exista linii de cod ce nu se termina cu ";".
$_= "x = 1;\n y = 2\n z = 3\n";
$nr = s/(\w)(?=\n)/\1;/ig;
print "Numarul de modificari: $nr\n";
print "Rezultat:\n $_\n";
Analog se utilizeaza si constructia negativa, specificând caracterul sau caracterele care nu trebuie sa urmeze expresiei de cautat. Atentie însa: aceste expresii nu pot fi utilizate pentru specificarea unei eventuale constructii care trebuie sau nu trebuie sa preceada expresia de cautat.
Câteva exemple de utilizare a functiei de substitutie:
# Utilizarea parantezelor rotunde ca delimitatori:
s(/usr/bin)(/usr/local/bin);
# Utilizarea variabilelor în cadrul substitutiei:
s/Login: $var1/Login: $var2/;
# Memorarea numarului de înlocuri:
$nr_inlocuiri = ($linie =~s/Mister\b/Mr. /g);
# Utilizarea unei expresii ca expresie de înlocuire:
$_ = Pret = 111';
s/\d+/$&*2/e; # Pret = 222;
s/\w/$& x 2/eg; # Pprreett == 222222;
# Eliminarea spatiilor de la începutul si sfârsitul unei linii:
s/^\s*(.*?)\s*$/\1/;
# Interschimbarea primelor doua cuvinte:
s
Functia care realizeaza traducerea caracter cu caracter se numeste "tr" si are urmatoarea forma generala:
tr/caractere_de_cautare/caractere_de_înlocuire/cds
unde
c - indica complementarea setului de caractere de cautare; în acest caz lista efectiva a caracterelor de cautare va contine toate caracterele care nu sunt specificate în cadrul setului "caractere_de_cautare";
d - indica stergerea tuturor caracterelor din setul de "caractere_de_cautare" care nu au corespondent în setul de "caractere_de_înlocuire";
s - indica reducerea secventelor de caractere care au fost traduse cu acelasi caracter la o singura aparitie a respectivului caracter.
Aceasta functie practic nu foloseste expresiile regulate: stringul de intrare este parcurs caracter cu caracter, înlocuind orice aparitie a unui caracter de cautare cu corespondentul sau de înlocuire. Functia întoarce numarul de caractere înlocuite si/sau sterse.
O particularitate a functiei de traducere este aceea ca cele doua seturi de caractere pot avea proprii lor delimitatori care pot fi diferiti:
tr[a-z][A-Z]
tr(
Cele doua seturi de caractere pot fi de lungimi diferite cu mentiunea ca setul de caractere de cautare este întotdeauna mai mare sau egal cu cel al caracterelor de înlocuire. În cazul în care lista caracterelor de cautare este mai scurta decât lista caracterelor de înlocuire, comportamentul functiei de traducere depinde de prezenta modificatorului "d" astfel:
- absenta modificatorului "d" implica replicarea ultimului caracter din lista de înlocuire pâna când cele doua liste ajung la aceeasi lungime:
- prezenta modificatorului "d" indica stergerea caracterelor care nu au corespondent în lista de înlocuire:
$s = "Program Perl";
$s =~ tr/P/p/;
print "$s\n"; # Afiseaza: program perl
$s =~ tr/pr/rp/;
print "$s\n"; # Afiseaza: rpogpam repl
$s =~ tr/pr/?/;
print "$s\n" # Afiseaza: ??og?am ?e?l
$s =~ tr/ogamel?/OGAMEL/d;
print "$s\n"; # Afiseaza: OGAM EL
Lista caracterelor de cautare poate contine una sau mai multe aparitii ale aceluiasi caracter, caz în care traducerea se realizeaza doar prin corespondentul primei aparitii a caracterului. Exemplul:
tr/aaa/123/
va face traducerea literei "a" în cifra "1".
Corespondenta între caracterele de cautare si cele de înlocuire se stabileste la compilare. Aceasta implica utilizarea functiei eval daca se doreste folosirea varibilelor în cadrul functiei de traducere.
eval "tr/$lista_de_cautare/$lista_de_înlocuire"
Câteva exemple de utilizare a functiei de traducere:
tr/A-Z/a-z
# Traducerea literelor majuscule în
# litere minuscule din variabila $_.
$nr = $dat =~ tr/=/=/
# Numararea semnelor de egalitate din
# variabila $dat.
tr/a-zA-Z//s
# Înlocuirea aparitiilor succesive ale
# aceluiasi caracter cu o singura
# aparitie: "buuumm" devine "bum"
tr/a-zA-Z/ /cs
# Traducerea tuturor caracterelor care nu
# sunt litere in spatii.
Divizarea unui string dupa o expresie regulata se realizeaza apelând la functia split. Cu ajutorul acestei functii, un cuvânt poate fi despartit în caractere, o propozitie poate fi despartita în cuvinte, iar un paragraf în propozitii sau chiar cuvinte:
@caractere = split(//, $cuvant);
@cuvinte = split(/ /, $propozitie);
@propozitii = split(/\./, $paragraf);
Dupa cum se poate lesne deduce, functia split primeste doua argumente: delimitatorul dupa care se face împartirea stringului, si stringul respectiv. În cazul obtinerii sirului de caractere al unui cuvânt, delimitatorul este sirul vid. În cel de-al doilea caz s-a considerat ca toate cuvintele propozitiei sunt despartite de spatii, iar în cel de-al treilea caz ca propozitiile sunt despartite de ".".
Un argument în plus în favoarea Perl
O problema celebra în domeniul prelucrarii limbajului natural este de a cauta în cadrul textelor mari si foarte mari, o anumita expresie regulata (de exemplu, unul sau mai multe cuvinte care apar într-o anumita ordine: "Perl ... PCReport"), si de a afisa sirurile de caractere gasite, împreuna cu un context mimim în care acestea apar. Afisarea ar trebui sa alinieze în aceeasi coloana primele cuvinte din sirurile de caractere care satisfac expresia regulata, în vederea prelucrarii rapide a rezultatului.
Problema nu este complicata si nici greu de rezolvat. Încercati sa o rezolvati utilizând limbajul C sau Java. Veti constata ca timpul alocat rezolvarii se masoara în ore si ca lungimea programului nu este deloc neglijabila.
În schimb, un programator de Perl rezolva aceeasi problema în câteva minute, iar lungimea programului este mult mai mica în comparatie cu implementarea din C sau Java. Pentru a va convinge de acest adevar atasam în listing 2 implementarea problemei în limbajul Perl.
Ing. drd. Raibulet Claudia este în prezent studenta la doctorat la universitatea "Politecnico di Torino", departamentul de informatica. Poate fi contactata la adresa [email protected]. ing. Ovidiu Constantin este în prezent consultant la firma Quinary S.p.a. din Milano. Poate fi contactat la adresa [email protected]
|