Perl (Practical Extraction and Report Language) è un linguaggio di programmazione creato nel 1987 da Larry Wall. Il linguaggio fu costruito per trattare testi e si ispirò a SED, AWK, allo shell scripting sh, ed al C. Il risultato è un linguaggio tanto potente quanto farraginoso e criptico. La potenza gli deriva dalla estesa capacità di trattare i dati tramite espressioni regolari, e qui la cripticità è inevitabile o quasi; la farraginosità è nella ridondanza degli operatori (vari operatori logici), nella parziale polisemia (<< e <<EOT rispettivamente shift e delimitatore di stringa) e nella variegata struttura di alcuni operatori (interfissa negli operatori di sostituzione: s/sostituendo/sostituente/opzioni). Ciò giustifica alcune delle definizioni o caratteristiche di cui si fregia: “C’è più di un modo di fare le cose” e “Il coltello dell’esercito svizzero dei linguaggi di programmazione”. La nascita di Perl coincide con l’inizio dell’espansione del WEB, che ne ha sfruttato le caratteristiche come linguaggio CGI.
Con la sua diffusione Perl si è arricchito di una grande varietà di moduli: moduli per il networking, per l’utilizzo di database, moduli matematici, ecc….
Tecnicamente Per si presenta come un linguaggio interpretato, in realtà i programmi sono tradotti in codice intermedio (dalla versione 6 in una macchina virtuale di nome Parrot).
prefisso |
macrotipo |
$ |
Numero o stringa |
@ |
Matrice o lista |
% |
Tabella hash |
& |
Funzione (in istruzione print) |
Non c’è tipizzazione per i tipi di dato elementari, le stringhe o i numeri (scalar) sono tali per il contesto in cui si usano. C’è invece la tipizzazione per i macrotipi: il prefisso delle variabili indica il macrotipo, secondo la tabella qui a lato.
L’individuazione dei blocchi di istruzione è data da {parentesi graffe}, e le istruzioni sono terminate da “;”. L’ambito di vita delle variabili è sempre globale, tranne per le variabili di controllo dell’istruzione for e le variabili precedute da my, che vivono nell’ambito del blocco in cui sono dichiarate.
Una caratteristica, utile, di Perl è l’assegnazione automatica di certe informazioni a variabili predefinite e la possibilità di modificare il comportamento dell’interprete agendo su alcune di loro:
Variabile |
Nome mnemonico (*) |
Descrizione |
$0 |
$PROGRAM_NAME |
Nome dello script in
esecuzione |
$_ |
$ARG |
Variabile letta da file,
elemento di un for su liste, … |
@_ |
|
Lista dei parametri
passati ad una funzione |
$1,$2,... |
|
Componenti estratti da una
stringa tramite espressione regolare |
$. |
$INPUT_LINE_NUMBER,$NR |
Numero di riga dell’ultimo
file letto |
$! |
$OS_ERROR, $ERRNO |
Codifica dell’errore |
$@ |
$EVAL_ERROR |
Codifica dell’errore generato
da istruzione eval |
$& |
$MATCH |
Stringa che soddisfa
l’ultima espressione regolare |
$[ |
|
Indice del primo elemento
di un indice o sottostringa, default 0 |
* nomi utilizzabili
tramite la clausola: use English; |
Le funzioni restituiscono o il dato che indica l’istruzione return, o, se questa manca, l’ultima assegnazione effettuata.
Fra le caratteristiche che permettono la scrittura di programmi compatti si ha: la valorizzazione delle variabili nelle stringhe (variable interpolation), l’operatore di match // che confronta espressioni regolari e ne estrae le parti, il valore falso se una variabile è indefinita.
Qui di seguito un piccolo campionario di “attrezzi” di Perl (il risultato, ottenuto tramite l’istruzione print o printf, è segnalato da >> :
#
concatenazione (.) e prodotto (x) fra stringhe
printf
"--".('+--' x 3);
>>
--+--+--+--
#
incremento su stringhe A+1 = B e while in post-condizione
$a = 'A';print $a++ while ($a ne 'AA');
>> ABCDEFGHIJKLMNOPQRSTUVWXYZ
$a = "1.2.3";printf "%d punti",$a
=~ tr /././;
>>
2 punti
Nell’esempio che segue il programma riceve un
numero e ne determina il segno mediante l’utilizzo di sottrazioni e addizioni
di 1:
#This is perl, version 5.005_02 built for dos-djgpp sub
space {return ' ' x (@_[0]*3);} # @_ vettore degli argomenti $bar=$ARGV[0]; $ck = 0; $sw = 1; $alt ="10"; if ($bar != 0) { while ($bar != 0) { $sw =
substr($alt,$sw,1); $ck = $ck + 1; $frm = '$bar' .
substr("++--",$sw*2,2); # $bar++ o $bar-- for $i (1 .. $ck) { eval($frm) } printf
"%2d%s%4d\n", $ck,space ($sw), $bar; } print "\n $ARGV[0] e' ",
substr("negaposi",$sw*4,4),"tivo\n"; } |
Il risultato del programma è:
C:\fsf\lib\perl5>perl
segnonum.pm -3
1 -2
2
-4
3 -1
4
-5
5 0
-3 e' negativo
D:\fsf\Perl>
perl prova.pl 2
1 3
2
1
3 4
4
0
2 e' positivo
Nell’esempio
che segue Perl è utilizzato per generare l’indice HTML di questo manuale; una
macro in Basic WordScript genera l’elenco dei paragrafi (v. par. 2.7.1.3), lo script Perl legge lo schema della pagina,
inserendo i capitoli con eventuale collegamento alla pagina WEB, se è presente
il file Cap_TitoloCapitolo o se indicato nello schema (righe che
iniziano con -- ).
#This is perl, version 5.005_02 built for dos-djgpp
#
input: I canovaccio indice in HTML, II indice estratto da Word
#
output : indice HTML con il link ai capitoli pubblicati
#
Il link è creato se c'è un file Cap_titolocapitolo.htm
#
oppure se è indicato nel canovaccio (righe con -- all'inizio)
use
File::stat; # per avere i nomi dei
campi forniti da stat
sub
data { # $_ contiene una lista di 9
componenti data e ora
# mese 00-11, anno 0 = 1900
return
"$_[3]/".sprintf("%02d/",$_[4]+1).sprintf("%d",$_[5]+1900);
}
open(InputFile,
$ARGV[0]) or die "Impossibile aprire il canovaccio";
open OutputFile, "> $ARGV[2]"; # > aperura in output di indice HTML
while ($riga = <InputFile>) {
if ($riga =~ /^-- /) { # Link indicato nel canovaccio
if ($riga =~ /^--
Cap_(.*.)(htm'>)(.*)/) {}
$capitoli{substr($1,0,-1)} =
"$1$2$3"; # tabella capitoli
}
elsif ($riga =~ /^---- /) { # punto di iserimento dell'indice
open(InputFile2, $ARGV[1]) or die
"Impossibile aprire l'indice WORD";
while (<InputFile2>) { # le righe sono in $_
($paragrafo, $titolo) = /(.*\t)(.*)/; # prelevo parag. e nome del capitolo
$riga = "<BR>".(' ' x (1
+ $paragrafo =~ tr/././))."CAPITOLO
TITOLO";
$titolo =~ tr/*<>\//____/; # sostituisco *, <,> e / nel titolo
con _
if (($link = $capitoli{$titolo}) gt '')
{$riga =~ s/TITOLO/RIFV/;}
$x = stat($fl =
"Cap_".$titolo.".htm");
if ($x) {
$riga =~ s/TITOLO/RIFN/;
$datamod = data(localtime($x->mtime));
}
$riga =~ s/CAPITOLO/$paragrafo/;
$riga
=~ s/RIFV/<A href='http:Cap_$link/;
$riga =~ s/RIFN/<A
href='http:Linguaggi\/$fl'>$titolo<\/A> ($datamod)/;
$riga =~ s/TITOLO/$titolo/;
print
OutputFile $riga,"\n";
}
}
else {
$riga =~
s/&data/data(localtime(time))/e; #
inserzione di data
print OutputFile $riga;}
}