1
Perl

Practical Extract and Report Language
Continut:
    1. Ce este Perl ?
    2. Resurse Perl.
    3. Utilizatori Perl.
    4. Stilul de programare Perl.
    5. Stocarea si rularea programelor Perl.
    6. Elemente Perl.
    7. Literali si Operatori.
    8. Bucle si sistemul I/O in Perl.
    10. Procesare de date
    11. I/O folosind Pipe si Apelarea functiilor sistem
    12. Cautare
    13. Despartire in cuvinte (parsing)
    14. Folosirea Perl in scrierea de programe CGI.    

Note:
    1. Cele 4 paradoxuri Perl sunt evidentiate cu culoarea roz.
    2. Un exemplu de aplicatie CGI scrisa in Perl de mine, se gaseste la adresa:
        http://www.scs.ubbcluj.ro/~mr28602/serverstatus.cgi

1. Ce este Perl ?

    Perl este un limbaj de programare orientat spre extragerea , prelucrarea si prezentarea informatiei. Este disponibil pe o multime de platforme: Unix, MVS, VMS, MsDos, Macintosh, OS/2, Amiga si altele. Perl contine functii foarte puternice pentru manipularea textelor. El combina facilitatile si scopurile multor limbaje de comnezi (scripting). Perl a cunoscut succesul de curand, fiind folosit in programarea World Wide Web, la crearea formularelor electronice si in general ca o legatura intre sisteme, baze de date si utilizatori.

2. Resurse Perl.
    
    Acestea sunt cateva resurse pentru invatarea limbajului Perl.
web:                 www.cis.ufl.edu/perl
        www.perl.oreilly.com
grupuri usenet:  news:comp.lang.perl.anounce news:comp.lang.perl.misc
manual          :   Larry Wall, Tom Christiansen & Randall L. Schwartz, Programming Perl, 2nd         Edition September 1996, 670 pages, O'Reilly and Associates, Inc., ISBN 1-        56592-149-6, $39.95. The "Camel Book".

3. Utilizatori Perl.

    Doua categorii de programatori indragesc Perl. Administratori de sistem, deoarece imbina foarte elegant comenzi sistem pentru manipularea datelor si proceselor, si are facilitati de cautare care usureaza cautarile si afisarea de informatie intr-un sistem. Dezvoltatorii de aplicatii Web pe servere unix, deoarece este mai usor de invatat decat C si ofera mai multe functii decat acesta, respectiv pentru validarea datelor si gestionarea de baze de date simple.
    Codul Perl din acest document ruleaza sub Perl 4.036 (ultima versiune din seria 4) cat si sub Perl 5.0. Perl 5.0 adauga facilitati pentru programarea orientata obiect.

4. Stilul de programare Perl.

    Multe programe utile scrise in Perl sunt scurte. Sa presupunem ca vrem sa schimbam acelasi text in mai multe fisiere. In loc sa editam toate fisierele sau sa construim niste comenzi criptice in find, awk, sau sed , putem scrie o simpla comanda:

    perl -e 's/rosu/negru/gi' -p -i.bak *.html    

Acesta comanda, tastata la un promp Unix, executa programul Perl scris intre ghilimele. Acest program executa o singura operatiune: inlocuieste cuvantul rosu cu cuvantul negru , global, intr-un mod case-insensitive. Restul liniei de comenzi specifica, ca rularea sa se faca pentru fiecare fisier cu extensia .html din directorul curent, iar daca vre-un fisier trebuie modificat (test.html) atunci se va crea o copie de siguranta cu extensia .bak (test.html.bak).
    Pentru cei acomodati cu stilul de programare C sau Pascal, programul de mai sus poate fi expandat in forma urmatoare astfel incat sa urmareasca stilul de programare din cele doua limbaje de mai sus: (Pascal si C):
    
    #!usr/local/bin/perl -w
    #  File: schimb
    # Program Perl pentru substituirea cuvantului rosu cu cuvantul negru in toate
    # specificate in linia de comanda

    $vechi = 'rosu';
    $nou = 'negru;
    $nrschimbari = 0;

    # Separatorul de inregistrari in fisierele de intrare este definit de variabila globala     # Perl: $/ .Poate fi orice sir de caractere. In mod normal este \n . Aici il specificam     # ca fiind ca fiind null, deci intreg fisierul va fi citit ca un singur camp

    undef $/;

    # Presupunand ca programul a fost apelat cu parametrii schimb 1.html, 2.html,     # 3.html, atunci lista @ARGV va contine 3 elemente: ('1.html', '2.html, '3.html')
    # Acestia pot fi accesati prin $ARGV[0], $ARGV[1], $ARGV[2]

    foreach $file(@ARGV)
    {
        if (! open(INPUT,"<$file"))
        {
            print STDERR "Nu pot deschide fisierul $bakfile \n";
            next;
        }
    
    # Citesc fisierul de intrare ca si un singur camp de inregistrare
    $data = <INPUT>;
    close INPUT;

    if ($data =~ s/$vechi/$nou/gi)
    {
        $bakfile = "$file.bak";
        # Iesire daca nu pot salva fisierul de siguranta sau nu pot deschide fisierul         # destinatie
        if (! rename($file, $bakfile))
        {
            die "Nu pot redenumi $file $!";
        }
        if (! open(OUTPUT,">$file"))
        {
            die "Nu pot deschide fisierul destinatie $file \n";
        }
        print OUTPUT  $data;
        close OUTPUT;
        print STDERR "$file inlocuit \n";
        $nrschimbari++;
    }
    else { print STDERR "$file nu a fost schimbat\n"; }
    }
    print STDERR "$nrschimbari fisiere inlocuite. \n";
    exit(0);

    Observam din programul de mai sus ca anumite elemente se aseamana cu limbajul C. De exemplu linia in linia !open(INPUT,...) semnul ! este operatorul boolean de negare si se foloseste identic ca si in C, orice valoare pozitiva este adevarata, iar orice valoare pozitiva cu ! in fata este fals, iar 0 cu ! in fata este adevarat. Totodata observam ca si constructia if...else este similara cu ceea din C.
    In linia $nrschimbari++ observam ca incrementarea unei variabile se face analog ca in C.
    Filozofia Perl este :"There is more than one way", exista mai multe modalitati. Din acesta nobila libertate de exprimare rezulta prima din cele patru paradoxuri Perl: Programele Perl sunt usor de scris dar nu intotdeauna usor de citit. Pentru exemplificare, urmatoarele linii de cod Perl sunt echivalente.

    if  ($x == 0) {$y = 10;} else {$y = 20;}
    $y = $x == 0? 10 : 20;    
    $y = 20; $y = 10 if $x == 0;
    unless ($x == 0) {$y = 0;} else {$y = 10;}
    if ($x) {$y = 20;} else {$y = 10;}
    $y = (10,20) [$x != 10];

    Observam ca liniile 1, 2 si 5 sunt similare ca si sintaxa cu limbajul C. In multe aspecte Perl este similar cu C, dupa cum vom vedea si in cele ce urmeaza.

5. Stocarea si rularea programelor Perl.

    Exemplul Hello World. Continutul fisierului hello este:
    
    # !/usr/local/bin/perl -w
    if( $#ARGV >= 0) {$who = join(' ', @ARGV); }
    else {$who = 'World'; }
    print "Hello, %who! \n";

    Presupunem ca programul de mai sus este stocat in fisierul Unix ~/bin/hello. Programul poate fi rulat cu una din comenzile:
    
    perl ~bin/hello
    perl ~bin/hello oameni
    perl hello (daca ne aflam in directorul ~/bin).

    Pentru executarea acestui program ca si o comanda, trebuie parcursi urmatorii  pasi:
 Prima linie din program trebuie sa contina dupa #! calea spre comanda perl, asa cum s-a aratat si in exemplul de mai sus. Totodata in aceasta linie se pot specifica si optiuni de comanda, de exemplu -w (warnings - avertismente).
Pentru a permite citirea si executarea fisierului de catre toti utilizatorii trebuie introdusa comanda Unix:

    chmod  a+rx ~/bin/hello

Se editeaza fisierul ~/.cshrc sau ~/.login pentru a aduga directorul bin in calea de cautare a fisierelor executabile. In aceste fisiere se adauga o linie in genul:

    set path = ($path ~/bin)
Dupa acestea, programul se poate lansa in executie tastand hello.

6. Elemente Perl

Structurile de date in Perl.

Scalari pot valori numerice sau caractere, determinate de contextul in care apar.

    Exemple:
    123  12.4 5E-10 0xff (valoare hexazecimala) 0377(valoare octala)
    ' Eu sunt $nume si sunt in anul \n 2'
    "Ce mai faci?" "Inlocuirea valorilor $x si \n in \" ghilimele."
    `date` uptime -u`
    $x $lista[5] $tabela('key')

Ghilimelele simple ' ' permit doar inlocuirea in textul cuprins intre ele a semnelor \\ si \. Ghilimelele duble " " permit inlocuirea in textul cuprins intre ele si a variabilelor gen $nume si a caracterelor de control gen \n (linie noua). Ghilimelele intoarse ` ` permit toate inlocuirile de mai sus , dupa care incearca sa execute sirul rezultat ca si o comanda sistem si intorc textul afisat de sistem ca urmare a executiei comezi reprezentate de sirul de caractere.

Sirurile de scalari ( numite si liste) reprezinta scalari aranjati secvential.

    Exemple:
    ('Luni', 'Marti', 'Miercuri', 'Joi', 'Vineri', 'Sambata', 'Duminica')
    (1,2,3,4,5,6,7,8,9)    echivalent cu (1..9)
    (1,2,3,4,5,6,7) [2,4] echivalent cu (3,4,5)
    @Lista

Sirurile asociative, ajuta la retinerea anumitor lucruri des folosite:

    Exemple:
    $ZileInLuna('Ianuarie') = 31;  $Student('Muresan Robert') = 1;
    $NumeStudent{28602} = 'Muresan Robert';
    $Nota($NrStudent, $NrExamen) = 10;
    %lista_intreaga

Perl 5 permite permite combinarea celor mai de sus, cum ar fi liste de liste sau siruri asociative de liste.

Conventii de notare in Perl.

Numele variabilelor scalare incepe cu $, chiar si atunci cand ne referim la un element dintr-o lista. Numele variabilelor care reprezinta liste incepe cu @, iar numele unei variabile care se refera la o lista asociativa incepe cu %.
Listele sunt indexate cu paranteze patrate [] si contin inchis intre ele un indice, indexarea incepand cu [0] (ca si in C). In Perl 5 indicii negativi inseamna indexare de la capatul listei.
De exemplu $Zile[5] este al saselea element al element al listei @Zile si

    ('Luni','Marti','Miercuri')[1] este egal cu 'Marti'

Listele asociative sunt indexate cu paranteze rotunde () care cuprind intre ele un sir de caractere.
$var, @var si % var sunt 3 variabile distincte.

    @zile = (31,28,31,30,31,30,31,31,30,31,30,31);
                                  # o lista cu 12 elemente
    $#zile                             # Ultimul indice din lista zile; 11 in acest caz
    $#zile = 7;                     # Trunchiaza sau extinde lista zile la 7 elemente
    @zile                              # ($zile[0], $zile[1],...)
    @zile[3,4,5]                   # = (30,31,30)
    @zile('a', 'c')                   # echivalent cu ($zile{'a'}, $zile{'c'})
    %zile                               # (cheie1, valore1, cheie2, valoare2,...)

Limbajul Perl este case sensitive, astfel $VAR, $Var si $var reprezinta 3 variabile distincte.
Daca primul caracter dupa simbolurile $,%, sau @ este un caracter sau linii de despartire _ atunci restul numelui poate sa contina numere sau linii de despartire. Daca primul caracter este cifra atunci si restul numelui trebuie sa contina doar cifre. Perl are mai multe variabile ale caror prim caracter nu este alfanumeric. De exemplu $/ este separatorul de inregistrari. O variabila neinitializata are o valoare speciala nedefinit care poate fi aflata cu ajutorul functiei defined(). Valorile nedefinite se convertesc in functie de context in 0, null sau false.
    Variabila $_ este folosita implicit de Perl cand o variabila necesara unei operatii nu a fost specificata. De exemplu:
    <STDIN>;     # Atribuie o inregistrare din fisierul STDIN variabilei $_
    print;              # Tipareste valoarea variabilei $_
    chop;              # Elimina ultimul caracter din $_
    @cuvinte = split; # Imparte sirul $_ in cuvinte despartite de spatii, care devin                                          # elemente succesive ale listei @cuvinte

Variabilele $_, $1, $2, $3 si alte variabile implicite folosite de Perl creaza al doilea paradox Perl: "What you don't see can't help you or hurt you", ceea ce nu poti vedea nu te poate ajuta sau ranii.

Functii si subrutine.

    Functiile in Perl se declara cu simbolul & in fata, excpetie facand cazurile cand numele procedurii urmeaza dupa un cuvatn cheie cum ar fi sub.
    Exemplu:
    sub square{return $_[0] ** 2;}
    print "5 la patrat este ", &square(5);
Numele handlerelor de fisiere nu incep cu caractere speciale, si pentru a nu intra in conflict cu alte cuvinte cheie, acestea sunt notate cu litere mari : INPUT, OUTPUT, STDIN, STDOUT, STDERR, etc..

7. Literali si Operatori

    Exemple: Numere si Caractere
    
    #!usr/bin/perl
    print '013'  , 'este numar prim', 004, ' nu este numar prim.';
    print 7 + 3,' ' , 7 - 3
    $x = 7;
    print $x
    print 'Nu afiseaza variabila $x si linie noua \n .'
    print 'Afiseaza $x si line noua \n'
    $y = "Linie ce contin $x si se termina cu salt la linie noua \n."
    print $y;
    $y = "Con"."catena"."re";
    print $y

Acest program va afisa:

013 este numar prim 4 nu este numar prim. 10 4 Nu afiseaza variabila $x si linie noua \n.Afiseaza 7 si linie noua
Linie ce contine 7 si se termina cu salt la linie noua
Concatenare
    
    Observam ca instructiunea print nu sare la linie noua decat daca se specifica caracterul \n intre ghilimele "". Aceasta o greseala des intalnita in programele Perl.
Totodata observam operatorul . (punct) care are ca efect concatenarea celor trei siruri de caractere.
    
    Exemple: Comparatiile
    
    O greseala des intalinta in programele Perl este confundarea operatorului de atribuire = cu operatorul de comparare numerica ==.
    Totodata este recomandata folosirea operatorilor eq, ne, lt, gt pentru siruri de caracatere:
    
    if ( $x eq 'unu')
    {
        print 'Siruri egale.'
    }

8. Bucle si sistemul I/O in Perl.

Exemplu: Parametrii in linia de comanda si bucle iterative
    
    print "$#ARGV este indicele ultimului argument din linia de comanda.\n"

    # Itereaza de la indicele 0 pana la indicele $#ARGV:
    # Observam ca , constructia for este similara cu cea din C

    for($i = 0; $i <= $#ARGV; $i++)
    {
        print "Paramtrul $i este $ARGV[$i].\n";
    }
    
    # O alta varianta a buclei de mai sus
    
    foreach $item(@ARGV)
    {
        print "Cuvantul este: $item. \n";
    }

    # O varianta similara folosind de data asta variabila implicita Perl $_

    foreach (@ARGV)
    {
        print "Spun: $_ . \n";    
    }

Rularea programului va afisa:

    > perl exemplu.pl Buna Dimineata, Elevi!    
    2 este indicele ultimului argument din linia de comanda
    Parametrul 0 este Buna.
    Parametrul 1 este Dimineata,.
    Parametrul 3 este Elevi!
    Cuvantul este: Buna.
    Cuvantul este: Dimineata,.
    Cuvantul este: Elevi!
    Spun: Buna.
    Spun: Dimineata,.
    Spun: Elevi!.

Exemplu: Sistemul standard I/O
    
    print STDOUT "Tastati un text: ";
    while($input = <STDIN>)
    {
        chop $input;
        print STDOUT "Ati tastat : $input \n"
        if ($input eq '') {print STDERR "Nu ati tastat nimic!\n"}
        print STDOUT "Mai tastati ceva sau apasati CTRL - D pentru terminare"
    }
    print STDOUT "Atat a fost."


1 Obs1. Conditia din directiva while este o directiva de asignare, asigneaza urmatoarea inregistrare de la intrarea standard, variabilei $input. La sfarsit de fisier acesta nu va asigna variabilei $input valoarea null, ci o valoare nedefinita, care in acest context este evaulata ca fiind null. Deci lini a while($input = <STDIN>) face trei lucruri: citeste o inregistrare, o asigneaza variabilei $input si verifica daca $input este nedefinita, in acest context ea fiind evaluata la valoarea null. In alte contexte, Perl evauleaza o variabila ca fiind zero sau null. De exemplu daca $i nu este definita, atunci $i++ va atribui variabilei $i valoare 1. De aici rezulta al treilea paradox Perl:  Side effects can yield an elegant face or a pain in the rear. Efectele secundare pot conduce la lucruri elegante sau batai de cap.
Obs2. Campurile de date sunt in mod implicit delimitate de caracterul \n, care in exemplul de mai sus este inclus ca si ultimul caracter al variabilei $input. Functia chop elimina acest ultim caracter din variabila $input. In Perl 5 este introdusa o noua functie chomp care elimina ultimele caractere doar daca acestea sunt definite ca delimitatori de inregistrari, prin variabila globala $/.

Exemplu: Executarea unui string ca si porgram Perl

    #!usr/bin/perl
    for(;;){
    print '(', join(', ',@Result),') ?';
    last unless $Input = <STDIN>;
    $? = ''; $@ = ''; $! = '';
    @Result = eval $Input;
    if ($?) {print 'status=', $?,' '}
    if ($@) {print 'eroare=', $@,' '}
    if($!) {print 'nreroare=',$!+0,': ',$!',' '}
    }

Functia eval, evalueaza un sir de caractere interpretand-ul ca un program scris in Perl. $@ reprezinta mesajul de eroare rezultat din ultimul apel al functiei eval sau do.
Rularea programului va afisa:

    >perl perls.pl
    () ? sqrt(2)
    (1.4142)

Exemplu: I/O cu fisiere

    #! usr/bin/perl
    # program pentru inversarea fiecarei linii dintr-un fisier.

    # 1: Obtinerea numelui fisierelor din parametrii transmisi in linia de comanda

    if($#ARGV != 1){
        die "Folosire: $0 fisier_sursa fisier_destinatie \n";
    }
    ($infile,$outfile) = @ARGV;
    if (! -r $infile){
        die "Nu pot citi fisierul de intrare $infile \n";

    }

    #2: Validarea fisierelor
    # Daca prima parte a expresiei in cazul operatorului || (or) este adevarata, Perl     # nu mai evalueaza si restul continutului. Daca fisierul de intrare sa putut     
            # deschide atunci executia programului continua, altfel se evalueaza instructiunea     # die si executia programului se incheie.

    open($INPUT,"<$infile") || die "Nu pot deschide fisierul $infile ! \n";
    if( -e $outfile){
        print STDERR "Fisierul $outfile exista!\n";
        until ($ans eq 'i' || $ans eq 'a' || $ans eq 'e'){
            print STDERR "Inlocuiesc, Adaugare, or iEsire?";
            $ans = getc(STDIN);
        }
        if ($ans eq 'e') {exit}
    }

    if ($ans eq 'a') {$mode = '>>'}
    else {$mode = '>'}
    
    open(OUTPUT,"$mode$outfile") || die "Nu pot deschide fisierul destinatie!";

    #3: Citeste fiecare linie din fisierul sursa, inverseaza linia si o scrie in fisierul     # destinatie

    while(<INPUT>){
        chop $_;
        $_ = reverse $_;
        print OUTPUT $_,"\n";
    }
    
    #4: Terminare

    close INPUT, OUTPUT;
    exit;

10. Procesare de date.

    Exemplu: Tabel cu rezultatele studentilor.
Programul produce un raport cu rezultatele studentilor la examene, combinand date din doua fisiere ce contin informatii despre studenti respectiv notele obtinute de fiecare la examene.
    Fisierul de intrare studenti are campurile delimitate prin : si contine pe fiecare linie numarul matricol, numele si anul in care este studentul.
    28602:Muresan Robert:2
    38601:Pop Ioan:3
    48000:Pop Vasile:1
    Fisierul de intrare note are campurile delimitate prin spatii si contine pe fiecare linie numarul matricol, examenul, si numarul de credite obtinute.
    28602 1 4
    38601 1 2
    48000 1 1
    28602 2 5
    38601 2 3
    Se observa ca Pop Vasile a lipsit la al 3-lea examen.
    
    Raportul afisat de program arata in felul urmator:
    
    Nr. Mat    Nume                  1    2    Total
    28602      Muresan Robert   4    5    9
    38601      Pop Ioan              2    3    5
    48000      Pop Vasile           1           1
                   Total:     7    8    
Programul care a generat acest raport este urmatorul:

    #! usr/bin/perl
    # Catalog de Note - pentru demonstrarea lucrului cu sistemul I/O, liste asociative     # sortare si formatarea unui raport
    # Programul accepta orice numar de studenti si examene, respectiv trateaza si     # cazurile cand anumite informatii lipsesc.
    $studfile = 'studenti';
    $notfile = 'note';

    # Daca fisierele se pot deschide, atunci perl nu mai evalueaza si restul expresiei ce     # urmeaza dupa ||

    open (NUME,"<studfile") || die "Nu pot deschide fisierul $studfile! \n";
    open(NOTE,"<notfile") || die "Nu pot deschide fisierul $notfile! \n";
    
    # Construieste o lista asociativa cu informatiile despre studenti folosind ca si     # cheie, numarul matricol
    
    while(<NUME>){
        ($nrmat,$nume,$an) = split(':',$_);
        $nume{$nrmat} = $nume;
        if (length($nume) > $maxlengthnume){
            $maxlengthnume = length($nume);
        }
    }
    close NUME;

    # Construieste un tabel cu notele de la exemene

    while(<NOTE>){
        {$nrmat,$nrexam,$nota} = split;
        $nota{$nrmat,$nrexam} = $nota;
        if ($nrexam > $maxnrexam){$maxnrexam = $nrexam;}
    }
    close NOTE;

    # Tipareste raportul cu datele citite

    printf "%6s %-${maxlengthnume}s ",'Nr. Mat','Nume';
    foreach $nrexam(1..$maxnrexam){
        printf "%4d",$nrexam;
    }
    printf "%10s\n\n",'Total:';
    
    #  Subrutina dupanume este folosita pentru sortarea sirului %nume
    #  Functia "sort" transmite variabilele $a si $b subrutinelor pe care le apeleaza
    # Functia " x cmp y " returneaza  -1 daca x < y , 0 daca x=y si 1 daca x > y.

    sub dupanume {$nume{$a} cmp $nume{$b}}
    
    # Ordoneaza numerele matricole astfel incat numele studentilor sa apara in     # ordine alfabetica
    foreach $nrmat(sort dupanume keys(%nume)){
        # Tipareste creditele obtinute si totalul pentru fiecare student
        printf "%6d %-${maxlengthnume}s ", $nrmat,$nume{$nrmat};
        $total = 0;
        foreach $nrexam(1..$maxnrexam){
            printf "%4s",$nota{$nrmat,$nrexam};
            $total += $nota($nrmat,$nrexam);
            $examtot($nrexam) += $nota($nrmat,$nrexam);
        }
        printf "%10d\n",$total;
    }

    printf "\n%6s %${maxlengthnume}s ",' ',"Total: ";
    foreach $nrexam(1..$maxnrexam){
        printf "%4d",$examtot{$nrexam};
    }
    printf "\n";
    exit(0).
    
11. I/O folosind Pipe si Apelarea functiilor sistem.

    Exemplu: Afisarea spatiului ocupat de fisiere pe disc.

    #! usr/bin/perl
    # Afisarea spatiului ocupat de fisierele specificate
    # Acest program apeleaza functia sistem (Unix) du din care obtine numele     # fisierului si numarul de bytes ocupati, si reuneste aceste informatii cu alte     # informatii utile
    
    $files = join(' ',@ARGV);
    
    # Semnul | redirecteaza datele afisate de du catre programul nostru

    if(! open(DUPIPE,"du -sk $files | sort -nr |")){
        die "Nu pot rula du! $!\n";
    }
    printf "%8s %-8s %-16s %8s %s\n",'K-Bytes','Login','Nume','Modificat','Fisier';

    while (<DUPIPE>){
        # proceseaza informatiile afisate de du
        ($kbytes,$filename) = split;

        # apel sistem pentru aflarea mai multor informatii despre fisier
        ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime) =         stat($filename);
        
        #apel sistem pentru a asocia  login si nume cu uid
        if($uid != $previous_uid){
            ($login,$passwd,$uid,$gid,$quota,$coment,$realname,$dir,$shell)             = getpwuid($uid);
            $realname = split(', ',substr($realname,0,20));
            $previous_uid = $uid;
        }

        # Converteste timpul ultimei modificari intr-o forma mai usor de citit
        ($sec,$min,$hour,$mday,$mon,%myear) = localtime($mtime);
        $mmonth = $mon + 1;

        printf "%8s %-8s %-16s %02s-%02d-%02d %s\n",$kbytes,             $login,$realname,$myear,$mmonth,$mday,$filename;
    }
Exemplu de rezultat afisat de program:        
    
    K-bytes Login        Nume                   Modificat Fisier
     12345  mr28602   Muresan Robert  99-10-10   abc.txt

12. Cautare.

    Cautarea implica folosirea unor sabloane numite expresii regulare. Dupa cum se va vedea, aceasta da nastere la al patrulea paradox Perl: Regular expresion aren't. Expresiile regulare nu sunt(regulare).
    Operatorul =~ efectueaza cautarea dupa un sablon si inlocuirea. de exemplu, daca
    $s = 'Unu doi trei patru'';
atunci
    if ($s =~/doi trei/) {print YES} else {print NO}
va tipari YES, deoarece sirul de caractere $s se potriveste cu sablonul "doi trei"
    if($s =~/unu/){print YES} else {print NO}
va tipari NO deoarece sirul nu se potriveste cu sablonul. Adaugand insa optiunea i pentru a ignora diferenta intre caracterele mari si caracterele mici, atunci urmatoarele linii vor afisa YES.
    
    if($s =~ /one/i) {print YES} else {print NO}

Sabloanele pot contine o serie larga de optiuni pentru a face cautarea cat mai flexibila si generala.De exemplu un .(punct) se potriveste cu orice caracter, exceptand caracterul \n.
    
    if($s =~ /l.mp/){print YES}

va tipari YES pentru $s = "lamp", "lump", "slumped", dar nu si pentru $s = "lmp",sau "less amperes".
Parantezele () grupeaza elementele sablonului. Un asterisk * inseamna ca, caracterul, elementul, sau grupul de elemente anterior poate sa apara de mai multe ori sau deloc.Simila plus + inseamna ca elementul sau grupul de elemente anterior trebuie sa apara cel putin odata.Semnul intrebarii se potriveste cu o singura aparitie sau nici o aparitie.Exemple:

     /fr.*nd/  se potriveste cu "frnd", "friend", "front and back"
    /fr.+nd/  se potriveste cu "frond", "friend", "front and back"
                  dar nu se potriveste cu "frnd".
    /10*1/    se potriveste cu "11", "101", "1001", "100000001".
    /b(an)*a/ se potriveste cu "ba", "bana", "banana", "banananana"
    /flo?at/  se potriveste cu "flat" and "float"
                dar nu se potriveste cu "flooat"    

Parantezele patrate[] se potrivesc cu un singur caracter definit de ele. De exemplu:

    [0123456789] se potriveste cu orice cifra
    [0-9]                se potriveste cu orice cifra
    [0-9]+             se potriveste cu orice secventa de cifre
    [a-z]+              se potriveste cu orice cuvant scris cu litere mici
    [A-Z]+            se potriveste cu orice cuvant scris  cu litere mari
    [ab n]*            se potriveste cu sirul null "", sirul "b", orice numar de             spatii,"banana an nnna"             
    [^...]                se potriveste cu orice caracter care nu este "..."
    [^0-9]              se potriveste cu orice caracter care nu este cifra
    
Acoladele permit o specificare mult mai precisa a sirurilor care se repeta. Astfel [0-9]{6} se potriveste cu orice sir de cifre de lungime 6, iar [0-9]{6,10} se potriveste cu orice sir de cifre care are lungime cuprinsa intre 6 si 10.
Sabloanele pot sa apara oriunde in sirul de caractere daca nu sunt ancorate.Semnul ^ pus in afara parantezelor patrate[], ancoreaza sablonul la inceputul sirului de caractere, iar caracterul $ ancoreaza sablonul la sfarsitul sirului de caractere.De exemplu:

    /at/            se potriveste cu  "at", "attention", "flat", si "flatter"
    /^at/          se potriveste cu "at" si "attention" dar nu si cu "flat"
    /at$/          se potiveste cu "at" si "flat", dar nu si cu "attention"
    /^at$/        se potriveste doar cu "at".
    /^at$/i       se potriveste cu "at", "At", "aT", si "AT".
    /^[ \t]*$/   se potriveste cu o linie goala, sau cu o linie ce contine oreice                           combinatie de spatii libere sau taburi

Caracterul Backslash. In general caracterele se potrivesc cu ele insele, cu exceptie caracterelor speciale de control cum ar fi:+ ? . [] () {}. Acestea trebuie prefixate cu un backslash \ pentru a fi considerate ca si caractere.
Bara verticala | este operatorul binar sau. Exemplu:

    if ($answer =~/^y | ^yes |^yeah/i){
        print "Afirmativ";
    }
va afisa "Afirmativ" pentru: y, yes, Yes, Yeah, Yeah rigth,etc...

13.Despartire in cuvinte (parsing).

    Cand se includ paranteze rotunde in sabloanele de cautare, secventele cu care se potrivesc acestea, pot fi accesate folosind variabilele $1,$2,$3, etc.. in ordine de la prima paranteza din stanga. Aceste secvente pot fi asignate ca si elemente succesive ale unui sir.
Exemplu:
    
    #! usr/bin/perl -w
    $s = 'Acest sir contine 1 subsir de tip data 10/10/99 undeva.';
    
    # sirul /d semnifica un sir de cifre
    $s =~ /(\d{1,2})\/(\d{1,2})\/(\d{2,4})/;
    
    # varianta 1:
    print "\$1 = $1, \$2 = $2, \$3 = $3\n";

    # varianta 2:
    {$ziua, $luna, $an} = ($s =~ /(\d{1,2})\/(\d{1,2})\/(\d{2,4})/);
    print "$ziua, $luna, $an\n";

    #varianta 3:
    {$data,$ziua, $luna, $an} = ($s =~ /(\d{1,2})\/(\d{1,2})\/(\d{2,4})/);
    print "$data, $ziua, $luna, $an\n";

14. Utilizarea Perl in scrierea de programe CGI.

    Limbajul Perl poate fi folosit cu succes in scrierea de aplicatii CGI (Common Gateway Interface), acestea fiind folosite pe serverele de Web. Un program CGI ruleaza pe platforma Web Serverului , astfel chiar daca WebServerul este o masina Unix si utilizatorul acceseaza programul CGI de pe o platforma Windows, aplicatia CGI se poate rula fara probleme pe masina Unix, iar rezultatele afisate de aceasta sunt afisate in browserul utilizatorului.

    Exemplu: Afisarea starii serverului:
    Aplicatia foloseste comenzile unix 'uptime', 'hostname', si 'w'.
    Pentru a vedea rezultatele acestui program, vizitati adresa:
    http://www.scs.ubbcluj.ro/~mr28602/serverstatus.cgi
    
Programul este:    
    #! usr/bin/perl
    # Trimite mesajele de eroare catre utilizator, nu catre sistem
    open(STDERR,'<&STDOUT'); $| = 1;

    # Programul va furniza browserului, un fisier html
    print "Content-type: text/html\n\n";
    $host = `hostname`; chop $host;
    $uptime = `uptime`;
    $w = `w -s -h`;
    print <<BUNCHASTUFF;
    <Html><Head>
    <H1>Informatii despre serverul $host</H1>
    </Head><Body>
    $uptime
    <PRE>$w</PRE>
    <HR>
    </Body></Html>
    BUNCHASTUFF;
    exit;

    Pentru folosirea aplicatiei este necesar sa setam fisierului serverstatus.cgi, drepturi de acces, citire, si executi cu comanda Unix:

    chmod a+rx serverstatus.cgi

Cele mai ok referate!
www.referateok.ro