PERL

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;}

  }