Perl
informasjon
oppdatert: Mandag 9. september 2002
Perl (Practical Extraction and Report Language)

I Perl-skriptet spesifiserer en på første linje hvilken intepreter som skal benyttes. Perl-intepreteren ligger på våre webhotell i katalogen /usr/bin/. Første linjen i scriptet blir dermed som følger:
#!/usr/bin/perl -w

print "Content-type: text/html\n\n";
print "Dette er skrevet av Perl-skriptet \"demo.plx\"\n";

Skriptet over innholder videre et hodefelt som må være separert fra resten av innholdet med en blank linje. Print-kommandoen tolker tolker \n i teksten som tegnet for ny linje. Legg merke til at alle linjer i et Perl-skriptet avsluttes med semikolon. For å aksessere dette scriptet via link-element trykk her.
VIKTIG informasjon om hodefelt, filrettigheter og filekstensjoner se webserver-programmering.
VIKTIG å benytte ascii modus (ikke binary) ved ftp-filoverføring, da perl interpreteren må ha unix linjeskift.

Operatorer
Perl benytter de vanlige operatorene i java og c. Det viktigste aviket er pluss-tegn for sammensetting av strenger i java er byttet ut med punktum. Perl har i tillegg flere andre operatorerer:

  • eq, ne, lt, le, gt, ge kan benyttes for å sammenligne tekster
  • x-tegnet fungerer som multiplikasjons-operator for tekst-strenger, f.eks "abc"x3 betyr "abcabcabc".
  • =~ benyttes ved søking og substituering i tekst ved hjelp av regulære utrykk, se eget avsnitt om regulære utrykk
  • -> benyttes til å skille nøkkelnavn og verdi i oppramsing av hash-tabell elementer, se avsnitt om datatyper.
  • && og || kan benyttes mellom funksjoner. Eksempel: funksjon1 && funksjon2; Her vil kun funksjon2 utføres om funksjone1 var vellykket. Ved bruk av || er det motsatte tilfelle. Dette er analogt til bruk av operatorene mellom kommandoer i Bourne-shell
  • Listeoperatoren kan benyttes til samtidig tilordning av flere variabler:
    ($x,$y)=("en",2);
    Samtidigheten i tilordning kan nyttes ved "swapping" (to eller flere variabler som internt bytter verdi) av variabler.
    ($x,$y)=($y,$x);
  • For opereratorer på filhandlere benyttes omtrent halve alfabetet. Her følger et kort utdrag
    -rFilen lesbar
    -wFilen lesbar
    -xFilen kjørbar
    -eFilen eksisterer
    -zFilen er tom
    -sAntall byte i filen
    -dFilen er en katalog
    -dFilen er en named pipe
    -dFilen er en socket
    -CAntall dager siden inode ble endret

Anførsels-operatorene
Perl har en del anførsels-operatorer. Anføresels-operatorer kan omslutte teks-kontanter. Anførsels-operatoren er tilknyttet spesialtegn som gjør Perl-koden mer lesbar. Nedenfor følger en oversikt over anførsels-operatorer og alterntive spesialtegn.
OPERATORSPESIAL TEGNFORKLARINGINTERPOLATING
q//' 'Omslutter tekst konstantNei
qq//""Omslutter tekst konstantJa
qx//``Omslutter/utfører linux-kommandoerJa
qw//()Omslutter en liste av ordNei
m////Matching ved hjelp av regulært utrykkJa
s///s///Substituering ved hjelp av regulært utrykkJa
tr///y///Oversetter tegnNei
qr//""Omslutter regulært utrykkJa

I tekstkonstanter benyttes ofte escape-tegn, se liste nedenfor, for å kunne indikere tegn utenfor ascii-tegnsettet eller spesialtegn. I Perl kalles substitusjon av slike escape-tegn "interpolating". Betegnelsen er hentet fra mattematikken der vi er vant til at begrepet interpolering betyr å glatte ut grafen mellom punkter.

Escape-tegnene i Perl
kjenner vi igjen fra java og c:
KODEBETYR
\nNy line (LF)
\rVognretur (CR)
\tTabulator
\fNy side
\bSlette forrige tegn
\aBjelle
\eESC-tegnet
\0330Oktalverdi til tegnet (Ø)
\xD8Heksverdi til tegnet (Ø)
 
Noen Perl spesifikke escape-tegn:
KODEBETYR
\cCKontroll-c
\x{263a}UTF-16 verdi til tegnet (smil-tegnet)
\uOversette neste tegn til stor bokstav
\lOversette neste tegn til liten bokstav
\UOversette følgende tegn til store bokstaver
\LOversette følgende tegn til små bokstaver
\QLegge til bakoverlent skråstrek på alle følgende ikke alfanummeriske tegn
\EAvbryte \U, \L eller \Q

En bør her merke seg:

  • For å kunne benytte variabler i konstanter må en benytte doble anførselstegn.
  • Konstanter omsluttet av enkelt anførselstegn må minst avskilles med et blank tegn fra foregående ord for ikke bli feiltolket av Perl-intepreteren (se forklaring under package-kapitellet).
  • I anførseloperatorene kan en selv velge hvilken skilletegn du ønsker å benytte. Følgende er helt ekvivalent:
    $x='hei';
    $x=q/hei/;
    $x=q(hei);    #Valgt ikke standard skilletegn
    $x=q?hei?;    #Valgt ikke standard skilletegn

Datatyper, datastrukturerer og variabler
Perl har følgende datatyper:
TYPESYMBOLINNEHOLDER
SCALAR$et tall eller en streng
ARRAY@liste med verdier, indeksert av tall
HASH%gruppe av verdier, søkbart via nøkkelord
CODE&subrutiner
GLOB*alias, konstanter, handlere
REF peker til verdi
LVALUE  
IO::handle handle til filer og piper
CODE innholder subrutiner. Alle brukerdefinerte funksjoner kalles subrutiner, se eget avsnitt under "Program flytkontroll". GLOB omtales vanligsvis som "typeglob". IO::handle omtales vanlig hvis som "filhandle".

SCALAR
Scalar benyttes til å lagre tall eller tekst-strenger. Tall lagres som flyttall. Det er automatisk konverting mellom tall og tekst, slik at
if ("1"<2)
er sant. Navnet tall- og tekst-variabler prefikses med dollartegn ved tillordning og bruk av variablen$. Tilordningsoperatoren er likhetstegn, eks $varNavn="verdi";.

ARRAY
Perl array tilsvarer vektorer i java. For å indikere at operatorer og funksjoner skal tolke variablen som en liste benyttes prefikset @. Eksempler på tilording av lister:

@arrayNavn1=("tekst 1","tekst 2", "tekst 3");
@listNavn2=("tekst 1",100,200,3.14 );
@arrayNavn3=("tekst 1", $arrayNavn[1], $arrayNavn[2]);    #arrayNavn3 vil ha samme innhold som arrayNavn1
@arrayNavn4=(@arrayNavn1,@arraynavn2);    #arrayNavn4 vil først innholde elementen i arrayNavn1 og deretter elementene arrayNavn2
@arrayNavn5=("navn1","verdi 1","navn2","verdi 2","navn3","verdi 3");
@arrayNavn6=@arrayNavn1;    #Setter arrayNavn6 lik en liste som er kopi av arrayNavn1

En kan direkte referere til enkelt elementer i arrayen ved bruk tall-indeker. Eksempel på referanse til første element i arrayen arrayNavn2: $arrayNavn2[0]. Negative indekser blir tolket som indeksering bakfra slik at $arrayNavn2[-1] returnerer siste elemententet i arrayen som er lik 3.14. . For forklaring på bruk av dollar-tegn i stedet alfakrøll, se omtale av kontekst. Perl har noen standard funksjoner som opererer på arrayer:
pop(@listNavn) fjerne siste element i arrayn
shift(@listNavn) Fjerner første element i arrayn
push(@listNavn,"element 4") Legger nytt element inn bakerst i arrayn
sort(@listNavn) Sortere arrayn alfabetisk
@ARG er en predefinert array som innholder alle environment variabler.

Arrayer av arrayer kan deklares på følgende måte:

HASH
Hash er tabeller der en benytter nøkkelord istedet for tall for søke fram verdier. For å indikere at operatorer og funksjoner skal tolke variablen som en hash benyttes prefikset %. Eksempeler på tilordnig av hash-tabeller som vil innholde samme elementer:

%hashNavn1=("navn1"=>"verdi 1","navn2"=>"verdi 2","navn3"=>"verdi 3");
%hashNavn2=("navn1","verdi 1","navn2","verdi 2","navn3","verdi 3");
%hashNavn3=@arrayNavn5;

En kan direkte referere til enkelt elementer ved bruk nøkkelordet, f.eks $arrayNavn1{"navn1"} er "verdi 1". For forklaring på bruk av dollar-tegn i stedet for prosent-tegnet se omtale av kontekst. Perl har noen standard funksjoner for hash-tabeller:
keys(%hashNavn) returnerer en array med alle nøkler i hashen
values(%hashNavn) returnerer en array med alle verdier i hashen
@ENV er en predefinert hash som innholder alle programmets parametre

Kontekst
Mange operatorerer og funksjoner i Perl kan operere på både scalare- og array/hash-variabler. Operatorene og funksjonene kan ha ulik betydning med hensyn til kontekst. Kontekst er et viktig begrep i Perl. Konteksten angir forventet type resultat eller retur verdi til operatorerer og funksjoner. Det er fire typer kontekster:

  • Scalar-kontekst forventer et tall- eller en tekst-verdi. Eksempler:
    $x=("null","en");    #setter x lik "en", det siste elementet i listen.
    $x=@arrayNavn1;    #settes x lik 3, som er lik antall elementer i listen.
    I disse to tilordningene av x skiller Perl på lister og array. Alle elementer til listen vil plasseres i en midlertidig stakk. Siden dette er en scalar-konteks tilordnes kun siste elementet. Variablen arrayNavn1 vet at den er en array-variabel som befinner seg i scalar-kontekst og plassere derfor ingen elementer i den midlertidige stakken, men returner kun antall elementer i arrayen.
  • Liste-kontekst forvententer en liste eller tabell. Eksempler:
    @y=("null","en");    #setter y lik listen slik at $y[0] er lik "null" og $y[1]="en".
  • Boolean-kontekst forventer "true" eller "false". Perl tolker strengen "" og "0", tallet 0 samt variabler som ikke er tilordnet verdier som usann. Alle andre verdier er sanne. Operatratorer og funksjoner gir samme resultat som i scale-kontekst.
  • Void-kontekst forventer ingen retur verdi.

Referanser og datastrukturer
Det er to typer referanser: "hard" og "symbolic". Hard- og symbolic-referanser er analogt til hard- og symbolics-links til filer i Linux. Hard-referanser innholder noe tilsvarende adressen til hvor selve verdien er lagret (dette er også analogt til pekere i c). Symbolic-referanser innholer navn (labelen) på en variabel. Hard-referanser betraktes som en egen datatype i Perl. Tilordning av denne variablene skjer på flere måter:
TILORDNING AV REFERANSERBRUK AV REFERANSER
$hardRef1=\"tekst1";$$hardRef1
$hardRef2=\$x;$$hardRef2
$hardRef3=\@arrayNavn1;$$hardRef3[1], $${hardRef3}[1], $hardRef3->[1]
$hardRef4=\%hashNavn1;$$hardRef4{"navn1"}, $${hardRef4}{"navn1"}, $hardRef4->{"navn1"}
$hardRef5=\&subNavn1;&$hardRef5(), &${hardRef5}(), $hardRef5->()
$hardRef5=\*globNavn1; 
$hardRef6=["a1","b1",["tekst 1","tekst 2","tekst 3"]];$hardRef->[2][0], $hardRef->[2]->[0]
$hardRef7=["a1","b1",[@arryNavn1]];$hardRef->[2][0], $hardRef->[2]->[0]
hardRef6 og hardRef7 simulerer 2-dimensjonale arrayer. I dette eksemplet innholder hardRef6 og hardRef7 like elementer.

Symbolic-referanser en en tekst-variabel som innholde navnet på en variabel. F.eks $x="y"; der y er navnet på en scalar tekst eller tall-variabel. Her vil $$x=24; føre til at y blir lik verdien 24. Tilsvarende blir om y er en array da vil $x->[0]=24; sette første element i arrayen til 24. Om y er hash vil x->{"key"}=24; sette elementet med navn "key" til 24.

Vi har sett over at bruk av referanser kan simulere 2-dimensjonale arrayer. Alternativt kan de to-dimensjonale arrayene deklares ved:
ARRAY AV ARRAYREFERERE TIL ELEMENTER
@array6=["a1","b1",["tekst 1","tekst 2","tekst 3"]];$hardRef[2][0], $hardRef[2]->[0]
@array7=["a1","b1",[@arryNavn1]];$hardRef[2][0], $hardRef[2]->[0]

Arrayer og hash-tabeller kan også kombineres.

Filehandle
Filhandler referer til filer og pipes. Filhandle tilordnes verdi ved hjelp av open-funksjonen. F.eks kan to filer åpnes for henhonholdvis lesing og skriving ved følgende programlinjer:

open ( InnH, "<innfil.txt");
open ( UtH, ">utfil.txt");

Filhandlerene InnH og utH og referer til hver sin fil. En kan nå lese og skrive til filene ved å benytte på filhandlerene:

$linje=<InnH>;
print (UtH $linje);

Her leses neste linje fra filen som handleren InnH referer til. Linjeskilletegnet "\n" følger med på lasset og kan eventuelt fjernes med kallet: chomp($linje). Print skriver linjen til filen angitt av filhandleren. Legg merke til at det ikke er komma mellom filhandler og teksten som skrives ut

Det er predefinerte filhandlere for standard innput, output og error: STDIN, STDOUT og STDERR. I mang tilfeller vil dette være default handlere. F.eks vil <> lese fra STDIN og print-funskjonen skriver til STDOUT om ikke annet oppgis. Se omtale av open-funksjonen nedenfor for syntaks for å appende til filer og åpne piper.

Typeglob
Typeglob har har sammenheng med at det i perl kan deklares forskjellig typer variabler med samme navn. Den viktigse bruk av Typeglobal er ved eksport av variabler i moduler, se eget kapittel. I avsnitt over om referanser så vi hvordan en kan benytte typeglob til å lage alias for refanser til verdier i alle variabeltyper med samme variabelnavn. Her følger noe andre eksempler på bruk av typeGlob

  • Lage alias
    *a=*b;
    Dette betyr at a er et alias for b. I alle sammehenger er bruk av a og b ekvivalent.
  • TypeGlobale benyttes ved lagring av filhandlere:
    $MinHandle=*FilHandle;
  • Definering av konstanter:
    *PI=\3.14;
    PI er nå deklarert som kun en lesbar scalar.
Regulære utrykk
En av de sterkeste sidene til Perl er mekanismene for søking i tekst. Det er mulig å både søke å foreta substitusjon i henhold til regulære utrykk. Eksempler:
  • Søking: $tekst=~m/bil/;
  • Substituering: $tekst=~s/bil/bruktbil/g;
Anførselsoperatorene m// og s/// er omtalt i eget avsnitt over. Tildeoperatoeren vil søke igjennom teksten etter ordet bil. Ved første påtreff vil kommandoen returne med verdien 1. I det andre tilfelle vil alle forekomster av ordet "bil" bli byttet ut med "bruktbil" og antall. Prefikses ikke det regulære utrykket med g (global) vil substituering stoppe etter første substituering i teksten.

For dokumentasjon av regulære utrykk se beskrivelse av Javascript.

Program flytkontroll
Java syntaks for if-tester, while- og for-løkker er gyldig i Perl. Perl har i tillegg noe ekstra å by på og her kan nevnes:
  • unless er en if-test som utføres når betingelsen er falsk
  • until er en while løkke som utføres så lenge betingelsen er falsk. unless
  • foreach VAR LIST {- - - - } Løkkke som går igjennom elementer i LIST-arrayen. Nytte element plassers i VAR for hver gjennomløp.
  • Hver program-linje kan tillegges en if- og unless-test som bestemmer om setningen skal utføres eller ikke. Eks:
    print "tekst" if ($x==1);

Funksjoner
Funksjoner i Perl kalles subrutiner. Her følger eksemple på vanlig syntaks til definisjon av en subrutine vi her har kalt "sum"

sub sum {
   print (1+3);
}

Denne rutinen kan kalles ved å bruke en av følgende ekvivalente programlinjer

sum();
&sum;

Prefiksing med &-tegnet over gir interpreteren beskjed om tolke etterfølgende navn som en en subrutine. Rutinen kan alternativt defineres uten navn og sette en refaranse variabel til å peke på rutinen.

&sum=sub {
   print (1+3);
}

Rutinen over kan vi enkelt utvide til ta argumenter og returne verdier. Argumenter og returverdier overføres i arrayer. Argumenter overføres i arrayen med det spesielle variabelnavnet: $_. Arrayen $_ er definert lokalt til rutinenen. Aktuelle paremetere overføres "by name". Verdien i arrayen er alias for de aktuelle pararametrene slik at endring inne i rutinen på verdien til argumentene vil også endre den aktuelle parameteren på utsiden av rutinen. Definisjonen av rutinen sum kan nå bli som følger:

sub sum {
   print ($_[0]+$_[1]);
}

Rutinen kan kalles på følgende måte:

sum(1,2);

Retur verdi til rutiner er verdi generert av siste programlinje i rutinen eller verdi returnert av funkjonen return i rutinen. Rutiner kan returnere både scalar-, array- og hash-verdi, men avhengig av i hvilken kontekst funksjonen er kalt vil verdien eventuelt bli konvertert. Definisjon av rutinenen sum til å returne summen av argumentene blir som følger:

sub sum {
   $_[0]+$_[1];
}

Eksempl på bruk av denne subrutinen. Begge kallene nedenfor er ekvivalente. Subrutiner trenger ikke å omslutte sine argumenter med parantes:

sum(1,3);
sum 1,3;

For å bruke subrutiner før de er definert ( selve programkoden ) må de deklareres.

sub sum($$);     #deklarsjon av sum
print sum(1,3);

sub sum($$){     #definisjon av sum (PS definasjonen må nå inneholde argument-typer)
$_[0];+$_[1];
}

En kan også merke seg at det er lovlig med rekursive kall på rutiner.

AUTOLOAD
Vanligvis kan en ikke kalle på en subrutine som ikke eksisterer, men i Perl er mulig å ha en default rutine som benyttes om ingen annen passer. Denne rutinen må navnet AUTOLOAD. Hvert navnerom (se forklarin i kapittelt "Package, symbol-tabell og scoped til variabler" ) kan ha sin AUTOLOAD rutine.

Package, symbol-tabell og scoped til variabler
Package definerer navnerommet til variabelnavn. Angis ikke ekspslitt noe navnrom tilhører variabelnavnene "main::". Navnrom kan endres ved bruk av package funksjonen som tar som argument navnet på rommet, f.eks:

$a=1;
package To;
$a=2;
print $a;     #skriver ut: 2
print $main::a;     #skriver ut: 1
package main
print $a;     #skriver ut: 1
print $To::a;     #skriver ut: 2

Alle variabelnavn tilhørende et navnerom lagres i en symbol-tabell oppkalt etter navnerommet. Symbol-tabellen for navnerom "To" over er "%To::". Bare navn som begynner med bokstaver eller lav bindestrek kan lagres i symbol-tabellen. Alle variabler inkludert $! , $! og $_ har tvunget tilhørighet til main-rommet. Nøkkel i symbol-tabellen er navnet på variablene og verdien tilhørende typeglobe. For eksempel vil symbol-tabellen etter tilordning av $a i package To innholde følgende:

print $To::{"a"};     #skriver ut: *To::a

Ved å endre verdier i symbol-tabellen kan en lage alias.

$b="C";
@b=("D","E");
*a=*b;
print $main::a;     #skriver ut: *main::b
print "$a";     #skriver ut: C
print "@a";     #skriver ut: DE

Alias kan benyttes til å aksesser variabler innenfor en annen pakke uten å prefikse variabelnavnet med pakkenavnet. Det er også mulig å gjøre variabler og rutiner tilgjengelige uten prefiks i alle andre pakker ved å bruk funksjonen our, f.eks:

$a=1;
our $a;
our $b=2;
package to;
print $a.$b;      #skriver ut 12

Our gjør variablen direkte aksesserbar innenfor filen eller blokken den deklarer variablen i, uavhengig av pakke-grenser.

Scope til variabler
Scope til variabler er globalt om ikke annet er oppgitt. Om en definere en variabel inne i en annen {}-blokk eller subrutine kan de likevel aksesseres på utsiden. Tilsvarende for subrutiner. Ved bruk av package så vi over hvordan vi kunne knytte variabelnavn til ulike navnrom, men alle variablene kan forsatt aksesseres i alle rom ved å prefikse variablenavn med navnet på rommet. For å deklare en variabel eller rutine "lexically", som betyr kun aksessesbar innenfor en {}-blokk, må deklarasjonen prefikses med my eller local. Variabler og subrutiner prefikset med my vil ikke bli lagret i symbol-tabellen og "eksisterer" kun innefor {}-blokken subrutinen de er definert. My-variabler er aksessbar innenfor blokken uavhengig av pakkegrenser. Local lager ikke noen lokal variabler, men legger eksisterende verdi til global-variabel med samme variabelnavn og type på en stakk. Når programmet forlater {}-blokken eller subrutinen inneholdene local deklarasjon vil opprinnelig verdi til variablen hentes tilbake fra stakken. Koden nedefor viser et eksempel hva forskjellen mellom my og local utgjør i praksis:

$a=1;
{
local $a=3;
print inc();      #skriver ut 4
}

sub inc{
++$a};
}

Blir local her endret til my vil verdien 2 skrives ut.

Object
Perl simulerer klasser ved hjelp av package. Perl har ingen "new" operator til å generer instanser av klassen, men en bless-funksjon som knytter en referanse til navnerommet. Denne referansen referer også til en datatype, vanligvis en hash. Referansen blir dermed en referanse til en instans av klassen og innholdet i hashen blir betraktet som lokale variabler til denne instansen. Ved kall på metoder (metoder er subrutiner definert i navnerommet til klassen) vil hashen alltid automatisk bli plassert som første argument til metoden. Er referansen til klassen knyttet opp mot en annen datatype vil referanse til denne datatypen vil automatisk referanse til denne datatypen være oppgitt som første argument istedet for hashen.

Vi vil starte med et eksempel uten objekt-orientert programmering for å vise den lille endringen som gjøre for at det kalles objektorientert i Perl. Her vil vil lage en subrutine "skrivHash" i navnerommet "MinKlasse". Subrutinen tar som første parameter en referanse til hash. Den andre parameteren er et navn som benyttes som nøkkel i hashen til verdien som skal skrives ut:

package MinKlasse;
sub skrivHash{
my $hashRef=shift;
my $navn=$_[0];
print $hashRef->{$navn};
}

package main;
%i=("fornavn"=>"henrik");
$instans1=\%i;
MinKlasse::skrivHash($instans1,"fornavn");       #skriver ut: henrik

Nå skal vi gjøre eksemplet over om til objektorientert programmering i Perl:

package MinKlasse;
sub skrivHash{
my $hashRef=shift;
my $navn=$_[0];
print $hashRef->{$navn};
}

package main;
%i=("fornavn"=>"henrik");
$instans1=\%i;
bless($instans1,"MinKlasse");
$instans1->skrivHash("fornavn");       #skriver ut: henrik

Det er kun de to nederste programlinjene som er endret. Her benytter vi bless for knytte hash referansen "instans1" opp mot navnrommet "MinKlasse". I kallet på metoden "skrivHash" vil automatisk hashen, som "instanse1" refererer til, bli tillagt som første argument. Ved å definere er metode i klassen som kan benyttes som konstruktør blir syntaksen enda mer likt hva vi er vant til fra objektorientert programmering. Konstruktøren har vi naturlig nok kalt "new":

package MinKlasse;
sub new { bless {}}

sub skrivHash{
my $hashRef=shift;
my $navn=$_[0];
print $hashRef->{$navn};
}

package main;
$instans1=MinKlasse::new();
$instans1->{fornavn}="henrik");
$instans1->skrivHash("fornavn");       #skriver ut: henrik

Subrutinen "new" returnerer en referanse til en ny hash som er bless-et til navnreommet MinKlasse. Variablen "instans1" settes lik denne referansen og blir dermed en instanse av klassen "MinKlasse". Videre legges elementet "fornavn=>henrik" inn som lokale variable til "instans1". I eksemplet over kalles "new" som en subrutine med såkalt kvalifisert-navn (navn på subrutine eller variabel prefikset med pakkenavn etterfult av doble kolon). I stedet subrutine-kall bør metode-kall benyttes for "new". I eksemplet over benytter vi metode-kall på "instans1->skrivHash". Her er metoden kalt som en instans-metode. Det er også mulig å kalle metoder som klasse-metode. Kallet på "new" i eksemplet over kan kalles som en klasse metode som følger:

$instans1=MinKlasse->new();

Her bør en merke seg at navnet på klassen, altså "MinKlasse", blir automatisk oppgitt som første argument i klasse-metode-kallet. Perl har også en alternativ akvivalent syntaks som kan benyttes for kall på metoder som både instans- og klasse-metoder, f.eks:

$instans1=new MinKlasse ();

Nå begynnner dette å ligne svært på vanlig objekt-orientert syntaks. Videre kan vi modifisere vårt eksempel slik at lokale variabler blir initsiert av konstruktøren.

package MinKlasse;
sub new {
my $klasseNavn=shift;
my %hash=@_;
return bless(\%hash, $klasseNavn);

sub skrivHash{
my $hashRef=shift;
my $navn=$_[0];
print $hashRef->{$navn};
}

package main;
$instans1=new MinKlasse ("fornavn"=>"henrik");
$instans1->skrivHash("fornavn");       #skriver ut: henrik

En klasse kan arve metoder fra en annen klasse ved hjelp av arrayen @ISA. Ønsker vi f.eks. "DinKlasse" skal arve alle metoder i "MinKlasse" gjøres det som følger:

package DinKlasse;
our @ISA="MinKlasse";

package main; $dinInstans1=new DinKlasse ("dittnavn"=>"marie"); $dinInstans1->skrivHash("dittnavn");       #skriver ut: marie

For å finne korrekt methode i kall på "new" og "skrivHash" vil Perl sjekk i rekkefølge følgende seks muligheter:

  1. Sjekker klassen har subrutine med navnet, d.v.s. en subrutine med dette navnet er definert innenfor navnerommet instansen tilhører
  2. Sjekker om subrutinen er arvet fra fedre og stamfedre, d.v.s. en subrutine definert i en av klassene nevnt i @ISA-arrayen. Elementene i arrayen vil traverseres fra venster mot høyere og dybden før bredden.
  3. Sjekker om subrutine med dette navn i pakken UNIVERSAL::
  4. Perl gir å finner noe subrutine med dette navnet og sjekke om klassen har en AUTOLOAD subrutine.
  5. Perl sjekker alle aller fedre og stamfedre for AUTOLOAD subrutine
  6. Perl sjekker til slutt om de finnes en UNVIVERSAL::AUTOLOAD subrutine
UNIVERSAL er en innebygd klasse med 3-funksjoner i tillegg kan den innholde egendefinerte subrutiner. Her følger 3 eksempler på bruk av standard funksjonene:
  • $instans1->isa("MinKlasse");
    Subrutinen "isa" returnerer sant om instansen som kaller på den er medlem av klassen MinKlasse.
  • $instans1can("skriveHash");
    Subrutinen "can" returnerer sant om instansen har en subrutine med navn "skrivHash". Fedre vil også sjekkes.
  • $instans1->VERSION();
    Returnerer versjonsnummeret til klassen instansen peker til. Versjonen til klassen er deklarert i $VERSION variablen.
For definere private variabler og subrutiner i klassen benyttes my. Privat betyr generelt sett i objekt-orienterte språk at variablene og subrutinene ikke kan aksseres utenfor klassen de er definert. I Perl kan scopet til variabler og subrutiner kan begrenses til klassen (pakken) ved hjelp av my, se forklaring av my under avsnittet om "Package, symbol-tabell og scoped til variabler ".

Tied variabler
Ved bruk av "tie" får en nærmest tilgang til å overskrive event-methodene til variabler. Event-methoden blir kalt ved tilordning og utlesning. Her følger en liste methoder som implesitt blir kalt av operatorere på variablene.

SCALARARRAYHASH FILEHANDLE
TIESCALAR class, list TIEARRAY class, listTIEHASH class, listTIEHANDLE class, list
FETCH selfFETCH self, subscripT FETCH self, keyREAD self, scalar, length, offset
STORE self, valueSTORE self, subscript, value STORE self, key, value READLINE self
DESTROY FETCHSIZE DELETE self, keyGETC self
STORESIZE self, countCLEAR selfWRITE self, scalar, length, offset
CLEAR selfEXISTS self, keyPRINT self, list
PUSH self, listFIRSTKEY selfPRINTF self, format, list
POP selfNEXTKEY self, keyCLOSE self
SHIFT selfDESTROY selfDESTROY self
UNSHIFT self, list
SPLICE self, offset, length, list
EXTEND self, count
DISTROY self

Tie-funksjonen binder en variabel til en klasse som innholder methoder som overskriver standard event-methoden for variablen. Variablen er av type: scalar, array, hash eller typeglob. Typeglob representerer filhandler. Tie-funksjonen kaller respektiv konstruksjon-metode for hver av typene: TIESCALAR, TIEARRAY, TIEHASH eller TIEHANDLE. Her følger et eksempel på hvordan en kan oveskrive event-methodene til en scalar:

#! /usr/bin/perl

package kr;
sub TIESCALAR {bless \my $self, shift};
sub STORE {${$_[0]}=$_[1]};
    #default tilordning sub FETCH {printf "%.02f", ${my $self=shift}};     #avrunder til 2 siffer bak komma

package main;
tie $sum, "kr";
$sum=5*6.5647;
printf ("Total sum: $sum\n");     #skriver ut beløp med to siffer bak komma

Tie-funksjonen kaller på TIESCALAR i klassen "kr". Legg merke til at her benyttes "bless" på vanlig måte for å knytt en referanse til en scalar variabel til klassen "kr". Til forskjell fra vanlige klasse vil operatører på variablen "sum" kaller metoder i klassen "kr".

Module
Modul er en fil med Perl-kode som er egnet for gjennbruk. Filen må ha ekstensjon ".pm" og navnrommet til variablene må være likt navnet på filen (eldre moduler har filekstensjon ".pl" og "ph."). Det er to måter en en modul kan gjøre sitt intrface tilgjengelig overfor programmer: tradisjonell og objekt-orientert. Noe moduler tilbyr begge interfacer. Uansett interface importeres moduler i ditt program ved å tilføye øverst i programkoden:

use modulnavn liste

"Modulnavnet" er her likt navnet på en standard modul eller en egendefinert modul. Alle standard moduler som er tilgjengelig i våre webhotel befinner seg i katalogen /usr/lib/perl5/5.6.0/ og /usr/lib/perl5/site_perl/ (opprett en ssh-forbindelse og bruk ls-kommandoen på katalogen). "Liste"-argumentet kan benyttes ved tradisjonelt interface og innholder navn på de variabler og subrutiner en ønsker å importere fra modulen.

Objekt-orientert interface
I objekt-orient interface oppretter man en eller flere instanser av modulen. Variabler og subrutiner i modulen er deretter tilgjengelig ved vanlig objektorienter syntaks, eks på opprettelse av en instans av CGI-modulen:

$q= new CGI;      #oppretter insans q av CGI
$q->header(-type=>'text/html');      #skriver ut hode-felt

Tradisjonelt interface
I tradisjonelt interface eksporterer modulen navn på variabler og subrutiner inn i navnerommet til programmet der modulen benyttes. Her følger eksempel på en modul som eksporterer en rutine "fart" og variablen "merke" (koden må lagres i en fil kalt Bil.pm).

#! /usr/bin/perl
package Bil;
require Exporter;
our @ISA=qw(Exporter);
our @EXPORT=qw(&fart $merke);
our @EXPORT_OK=qw($farge);
our $VERSION=1.00;

$merke="Ferrari";
$farge="rød";
sub fart { printf "Du kjøre en %s %s i %.02f km/t\n",$farge, $merke, rand $_[0];}

Her følger eksempel på et program som benytter modulen (programmet må lagres i samme katalog som Bil-modulen)

#! /usr/bin/perl
use Bil;
$fartsgrense=100;
fart($fartsgrense);

Vi ser at Bil-modulen arver egenskaper til Exporter-modulen. I @EXPORT-arrayene angir en navn på variabler og rutiner som pr. default skal exporteres inn i navnerommet til programmet som benytter modulen. Modulen importeres i programmmet ved use-funksjonen. Use kan i tillegg til navn på modul ta en liste med navn på de variabler og rutiner en ønsker å importere. De oppgitte navn må også forekomme i @EXPORT, @EXPORT_OK eller @EXPORT_TAGS i modulen. Spesifiserer en ingen argument utenom modul-navnet use-funksjonen blir alle navn listet i @EXPORT importert.

Kompilatoren ser etter moduler i kataloger listet i @INC-arrayen. For legge til katalognavn kan følgende kode benyttes:

BEGIN{
push @INC, "/home/no/serlvets/perl/moduls/";
}

Begin-blokken utføres av kompilatoren før programmet starter. I eksemplet over vil nå kompilatoren i tillegg se etter moduler i katalogen "/home/no/servlets/perl/moduls/". Navn på egendefinerte moduler og variabler bør ikke innholde bare store eller små bokstaver da dette kan føre til sammenblanding med standard moduler.

Pragma-modulen
Pragma-modulen påvirker kompilatoren under utføring av ditt program.

CGI-modulen
Modulen innholder bl.a. subrutiner for å lese ut environment-variablen QUERY-STRING. Modulen har både tradisjonelt og objekt-orientert interface, her omtales kun det objekt-orientert. Oppgis ingen parametere ved instansiering av modulen vil QUERY-STRING leses inn, men det også mulig å direkte oppgi parameterverdier til instansen, her følger noen eksempler:

$s1=new CGI; #Leser envirionment variablen QUERY-STRING
$s2=new CGI (filhandler); #Leser parameterer på formen navn=verdi <linjeskift> fra filen.
$s3=new CGI (\*STDIN); #Leser parametere fra stdin
$s4=new CGI (%hashnavn); #Leser parametere fra hash
$s5=new CGI ($stringnavn); #Leser en streng formater som URL-søkestreng
$s6=new CGI (""); #Leser ingen parametere

Parameterverdien kan også leses ut igjen på flere ulike måter:
@navn=$s->param; #Plassere alle navn på parametrene i en array
@verdier=$s->param(@navn); #Plassere alle verdier til parametrene i en array
$s->import_names ("R"); #Lager en variable i navnerommet "R" for hvert "navn=verdi" par
$s->save (filhandle); #Skrive "navn=verdi" par til fil. Hver par er avskilt med linjeskift
$verdi=$s->param("navn"); #Henter ut verdien til parameter med navn "navn"
$s->delete("navn"); #Sletter en parameter par
$s->delete_all(); #Sletter all parametre

For ytterlige informasjon om CGI-modulen og andre moduler anbefaler vi å opprette en ssh-forbindelse til våre webhotell og les manualen eller selve perl-koden i modulen, f.eks for CGI-modulen kan en gi følgende kommandoer

perldoc CGI
more /usr/lib/perl5/5.6.0/CGI.pm

Samme dokumentasjon, men med bedre layout: http://perldoc.com/perl5.8.0/lib/CGI.html

Standard funksjoner
Perl har rundt 200 innebygde funksjoner. Her vil følger en kort omtale av funksjoner som er benyttet i eksempler i denne dokumentasjonen.
die melding; Funksjonenen avslutter programmet og skriver ut "melding" til standard error. Er meldingen en array vil elementene bli satt sammen til en streng.
exit n; Funksjonen avslutter programmet. Funksjonen tar eventuelt et utrykk som parameter. Utrykket blir utført og resultatet blir tolket som et heltall. Resultatverdien blir plassert i environment-variablen "status".
my variabler/subrutiner Variabler og subrutiner prefikset med nøkkelordet my vil ikke bli lagret i symbol-tabellen og "eksisterer" kun innefor {}-blokken subrutinen de er definert.
open HANDEL, "MODE sti"; Funskjonen benyttes til å åpne filer og piper. I avsnittet om filhandlere i kapittelet om "Datatyper, datastrukturer og variabler" vist eksempler på kommandoen. Vi ser der at at det benyttes en modifakator foran filnavn som bestemmer om filen åpnes for lesing eller skriving. Her er en oversikt over andre modifikatorer som kan benyttes.
MODELESE
AKSESS
SKRIVE
AKSESS
BARE
APPENDE
LAGE NY OM
IKKE EKSISTRER
OVERSKRIVER
EKSISTERNDE
< filstijaneineineinei
> filstineijaneijanei
>> filstineijajajanei
+< filstijajaneineinei
+> filstijajaneijanei
+>> filstijajajajanei
| kommandoneijan/an/an/a
kommando |janein/an/an/a

Eksempel på å åpne en pipe til printer: open PrintH "| lpr -Printer1";

our variabler our gjør variabler direkte aksesserbar innenfor filen eller blokken den deklarer variablen i, uavhengig av pakke-grenser. Til forskjell fra my lages her ingen lokal variabel.
print HANDLE liste Skriver ut liste. Listen har vanligvis kun et element og parantesene rundt listen kan da sløyfes. Default HANDLE er STDOUT.
rand tall Returnerer et tilfelding tall mellom 0 og "tall". Default verdi for "tall" er 1.
read HANDLE, SCALAR, lengde, offset Leser antall byte angitt av "lengde" fra en "HANDLE" inni variablen "SCALAR". Innlesningen starter etter "offset" antall tegn. Offset verdien er default lik 0.
ref REF Returnerer datatypen til verdien REF-variablen peker til, f.eks:

$a=1;
$b=\$b;
print ref $b;       #skriver ut SCALAR

Om referansen er blitt "bless" til en package vil pakkenavnet bli returnert.

require MODUL Her tilsvarende effekt som use MODUL med unntak av import av modulen skjer under kjøring og ikke under kompilering-fasen.

Oppgis det et versjonnummer istedet for modul-navn tolkes dette som om det kreves minimum oppgitt versjon av Perl-interpreteren for å kjøre koden.

split utrykk, tekst, limit ...; Funksjonen gir forskjellige verdier om den opperer i scaler- eller list-kontekst. I list kontekst vil funksjonen splitter opp en "tekst" til en liste. Teksten splittes med hensyn til forekomster av "utrykk"-et. "Utrykk" er et regulært utrykk. Limit kan settes til maks antall elementer i listen. Ved overskridelse av limit plassers resten av teksten i siste elementet. I scaler-kontekst returnes kun antall elementer.
use MODUL LIST Use laster inn en modul, om den ikke er lastet inn fra før, og importerer variabler og subrutiner til navnerommet hvor den kalles fra. Variabler og subrutiner importeres via alias, se avsnitt om typeglobe under kapittelet om "Datatyper, datastrukturerer og variabler". Følgende deklarasjoner er identisk:

use MODULE LIST;
BEGIN { require MODULE; import MODULE LIST;}

Begin-blokken tvinger require til laste inn modulen i memory under kompiliering. Import-rutinern tilører modulen. Det er ikke noe innebygd funksjon og det er opptil modulen og bestemme hvordan skal gjøre sine variabler og subrutiner tilgjengelig. Moduler med tradisjonelt interface arver import-rutinen fra Exporter-klassen.


Eksempel: Form to mail
Her følger skriptet som er benyttet i skjema omtalt i dokumentasjonen av CSS. Vi har lagt inn linjenummer for å referere til kommandoer (linjenummerene må fjernes før skriptet kan kjøres).

  1. #! /usr/bin/perl
  2. use Net::SMTP;
  3. use CGI;
  4. $s=new CGI;
  5. $s->import_names("R");
  6. print "Conent-type: text/plain\n\n";
  7. print $R::navn;
  8. $smtp=Net::SMTP->new('localhost');
  9. $smtp->mail('info@registrar.no');
  10. $smtp->recipient($R::epost);
  11. $smtp->data();
  12. $smtp->datasend("Subject: Demo av CSS og Perl\n");
  13. $smtp->datasend("\n");
  14. $smtp->datasend("Denne mail er usendt av et test eksempel vi har av CSS og Perl, der vi oppfordrer kunder til å skrive inn egen e-postadresse. Vi beklager om oppgitt e-postadresse ikke er korrekt. E-postadressen og eventuell annen oppgitt informasjon blir uansett ikke lagret hos oss.\n\nMed vennlig hilsen\nREGISTRAR.NO");
  15. $smtp->dataend();
  16. $smtp->quit;

  1. Lokaliserere Perl interpeteren som skal benyttes.
  2. Importere NET::SMTP-modulen.
  3. Importeres CGI-modulen.
  4. Lage en instans av CGI-modul. $s blir referanse til instansen. Instansen leser environment-variablen QUERY-STRING.
  5. Her vil alle par på formen navn=verdi i QUERY-STRING genere en variabel med navnet "navn" og tilordnes verdien "verdi". De variablen blir deklarert i navnerommet "R".
  6. Skriver ut hodefelt til stdout. Kun "Content-type" er plikt og legg merke til doble linjeskift mellom hodefelt og body.
  7. Begynner utskrift av selve bodyen som her kun inneholder verdien til parameter "epost".
  8. Lages en instans av Net::SMTP modulen som initsieres til å åpne en forbindelse til lokal smpt-server for utsendelse av e-post.
  9. Oppgir avsender
  10. Oppgir mottager
  11. Starter på selve data-blokken i meldingen
  12. Oppgir subject
  13. Mimefelt skilles fra selve innholdet i meldingen med et ekstra linjeskift
  14. Selve innholdet i meldingen
  15. Avslutter meldingen
  16. Avslutter forbindelsen til smtp-server.

    For mer informasjon om Net::SMTP modulen.

Eksempel: SQL-form
For å aksessere en sql-database fra et perl-skript, kan du gjøre følgende:
  • Inkluder linjen
    use DBI(); 
    øverst i skriptet.
  • Kall på funksjonen
    DBI->connect
    Som parametere oppgir du en URL på formen
    DBI:mysql:database=<din_database>;host=<hostnavn_eller_ipnr>
    samt brukernavn, passord og en hashtabell som brukes i forbindelse med feilhåndtering. I retur får du en database-handle.

    Eksempel:

       
       my $dbh = DBI->connect("DBI:mysql:database=testbase;host=db8.registrar.no",
    		       "testuser", "passord",
    		       {'RaiseError' => 1});
    
  • For å gjøre oppdateringer på basen, kall på $dbh->do(<sql-kall>);

    Eksempel:

       $dbh->do("INSERT INTO Ordrer (Vare, Antall) VALUES (?, ?)", undef, $vare, $antall);
    
    $dbh->do tar to standard parametere. Den første er selve sql-setningen, den andre benyttes ikke av MySQL. Etterfølgende parametere blir substituert for ? i selve sql-setnignen.
  • For å hente ut informasjon fra basen, kall først på
       dbh->prepare(<sql-kall>)
    
    som gir deg et statement-objekt. Kall på execute() på dette objektet, deretter kan du f.eks. kalle fetchrow_hashref() for å lese ut en og en linje.

    Eksempel:

       my $sth = $dbh->prepare("SELECT * FROM Ordrer");
       $sth->execute();
       while(my $ref = $sth->fetchrow_hashref()) {
           print "<tr><td> $ref->{'Vare'} </td><td> $ref->{Antall} </td>";
       }
       $sth->finish();
    
  • Når du er ferdig med å bruke basen, lukk forbindelsen med
       $dbh->disconnect();
    
Her følger skriptet som er benyttet i "SQL-form" eksemplet omtalt i dokumentasjonen av CSS. HTML-siden som kaller på skriptet inneholder to knapper, trykk her for å se skjemaet. En for å lagre og en for slette alle varer. Ved lagring oversendes parametrene vare og antall som plasseres i som en ny linje i tabellen Ordrer. Hele tabellen skrives til slutt ut:
#! /usr/bin/perl -w

use CGI;
use DBI();

$s=new CGI;
$s->import_names("R");

print "Content-type: text/plain\n\n";

my $dbh=DBI->connect("DBI:mysql:database=servl_2;host=db8.registrar.no", "servl_2", "passord", {'RaiseError'=>1});

if ($R::aksjon eq "Lagre"){
$dbh->do("INSERT INTO Ordrer (Vare, Antall) VALUES (?,?)",undef,$R::vare,$R::antall);
}

if ($R::aksjon eq "Slett alle varer"){
$dbh->do("DELETE FROM Ordrer");
}

my $sth=$dbh->prepare("SELECT * FROM Ordrer");
$sth->execute();
while (my $ref=$sth->fetchrow_hashref()){
print "<tr>";
print "<td class=feltVerdiV>$ref->{'Vare'}</td>";
print "<td class=feltVerdiH>$ref->{'Antall'}</td>";
print "<td></td>";
}

$dbh->disconnect();

ADVARSEL: Koden innholder passord til database. For å beskytte dine programfiler for innsyn må korrekte fil-rettigheter settes, se SSH.

Referanser
  • Bøker: "Programming Perl" av Larry Wall, Tom Christiansen og Randal Schwartz. Dette er biblen for perl-programmerere og kalles også "kamelboken" p.g.a. av bildet av dyret på forsiden.
  • Nyhetsgrupper: no.it.programmering.perl
  • www.perl.org
  • http://www.perldoc.com Dokumentasjon av Perl og moduler
  • http://www.perldoc.com/perl5.8.0/pod/perlintro.html Intro til Perl
  • www.cpan.org Comprehensive Perl Archive Network er det sentrale stedet for nedlasting av Perl intepreter, moduler og script.