[precedente] GIMP - Copertina - CDROM-edicola [successivo]

Articoli


Cos'è il PERL

Cosa voglio fare in questi articoli

Questo è il primo di una serie di articoli che non vogliono essere assolutamente un corso sul Perl, ma solo uno stimolo per far vedere quanto questo linguaggio possa essere utile nella ``vita di tutti i giorni''; per un corso intensivo del linguaggio si rimanda alla bibliografia che verrà via via fornita.

Un po' di storia del PERL

Prima della storia del PERL vediamo di capire cosa significa PERL!!!

P.E.R.L. è l'acronimo di Practical Extraction and Report Language o se si preferisce Pathologically Eclectic Rubbish Lister; non si sa quale delle due definizioni sia la più esatta: entrambe sono state dettate direttamente da Larry Wall, autore, mantenitore, implementatore di questo linguaggio.

Larry Wall creò il PERL quando tentava di produrre alcuni report da una serie di file; trovato che awk non soddisfava completamente le sue richieste decise di risolvere il problema scrivendo un tool general-purpose.

Oggi il PERL è diventato un linguaggio di programmazione disponibile su ogni implementazione di Unix, (ma lo si può trovare anche su sistemi diversi dagli Unix quali NT, OS/2 ecc..) la versione attuale è la 5.004 e lentamente sta crescendo e si sta perfezionando sempre più.

A cosa serve PERL

Per sapere cosa si può fare con Perl basta fare un bel man perl e leggere direttamente quanto scrive Wall: "Il Perl è un linguaggio interpretato ottimizzato per la scansione di file di testo arbitrari, l'estrazione di informazioni da questi file di testo e la stampa di report basati su queste informazioni. È anche un buon linguaggio per molti lavori di manutenzione di sistema. Il linguaggio è pesato per essere pratico (facile da usare, efficiente e completo) e non per essere bello (piccolo, elegante, minimale)", chi ha già una minima esperienza di Un*x può pensare che il Perl non faccia altro che fare tutto quello che può fare una semplicissima shell di sistema: questo però sarebbe un primo errore: proviamo infatti a pensare a quante sono le shell normalmente presenti in un sistema Un*x (csh, tcsh, zsh, bash...) e quanti linguaggi di script si dovrebbero imparare, in pratica uno per ogni shell. Con Perl un programma scritto su un sistema, ad esempio Linux, funziona su ogni sistema che faccia girare Perl senza essere minimamente modificato.

Perl è molto più conciso rispetto agli script di shell ed è molto più sicuro. Perl è inoltre il linguaggio di programmazione più usato per lo sviluppo di applicazioni CGI, ma è anche molto utile per la scrittura di applicazioni ftp, news, mail, accesso a database etc...

Proprio per la sua propensione per la scrittura di programmi CGI Perl sta diventando sempre più uno strumento utile al Webmaster.

Il linguaggio visto da vicino

Sintatticamente il Perl è molto simile al C, anche se naturalmente ci sono delle differenze.

Il Perl è un linguaggio interpretato, non è particolarmente semplice ma è anche dotato di una grande potenza e di una grande logicità. La definizione di linguaggio interpretato è però un po' limitativa: in realtà uno script prima di essere eseguito viene letto nella sua interezza, ne viene controllata la sintassi, viene compilato e quindi eseguito; alla fine dell' esecuzione il "compilato" viene rimosso dalla memoria. Spesso il Perl viene utilizzato per la creazione di prototipi di programmi che poi vengono sviluppati in altri linguaggi di programmazione, ed è estremamente comodo per la scrittura di programmi "usa e getta". Nella versione 5.xxx alla tradizionale programmazione procedurale sono stati aggiunti una più moderna programmazione orientata agli oggetti ed un supporto alla modularità.

Non sono ancora stati creati compilatori Perl, probabilmente perché non se ne sente una reale esigenza.

Un colpo d'occhio e capisci che...

Le variabili non devono essere dichiarate e la conversione fra tipi di variabile diverse avviene in modo automatico: è infatti possibile assegnare, ad esempio, un intero ad una stringa o viceversa senza nemmeno ricevere un ``warning'' dall'interprete-compilatore.

Le variabili che possiamo trovare sono di 3 tipi:

Per dati scalari si intendono:

Le variabili di tipo scalare sono identificati da nomi che iniziano obbligatoriamente con il carattere speciale "$" e possono avere nomi di lunghezza variabile:

$ma_guarda_come_e_lungo_il_nome_di_questa_variabile_perl
naturalmente non devono essere assolutamente inseriti spazi nel nome della variabile.

Variabili di tipo numerico

Tenendo presente che internamente il Perl considera i numeri come se fossero tutti nello stesso formato, ecco alcune semplici dichiarazioni di variabili numeriche:

Variabili numeriche di tipo floating point

2.25
1.39e55 # 1.39x10^55
1.39E55 # idem come sopra
-4.3e22 # -4.3x10^22
Variabili numeriche di tipo intero
199
1436
-22450
2849
Possono essere dichiarate variabili di tipo ottale facendo precedere il valore numerico per 0, oppure si possono dichiarare variabili di tipo esadecimale facendo precedere il valore numerico da 0x:
0xff    # Dichiara il valore esadecimale FF, corrispondente al valore 255 in decimale
0377    # Dichiara il valore ottale 377, corrispondente al valore 255 in decimale
Variabili di tipo stringa

Non sono altro che normali sequenze di caratteri e possono essere di due tipi, singled-quoted o double-quoted: vediamone qualche esempio:

'ciao'                  # stringa singled-quoted che corrisponde a 5 caratteri c, i, a, o
'l'apostrofo'           # stringa singled-quoted che corrisponde a l,',a,p,o,s,t,r,o,f,o
"Linux the choice of a\nGNU generation"         # Linux the choice of a GNU <newline> generation
"Linux" x 5             # corrisponde alla stringa "LinuxLinuxLinuxLinuxLinux"
Interessanti, e diversi da quelli del C, sono gli operatori da usarsi con le stringhe, li vediamo riassunti nella tabella seguente:
 
 
Tipo di comparazione Simbolo
Uguale  eq
Non uguale  ne
Minore lt
Maggiore gt
Minore uguale le
Maggiore uguale  ge
 

Array di scalari

Nulla in particolare da dire riguardo agli array di scalari, il cui concetto è simile a quello degli altri linguaggi di programmazione; il nome di un array deve iniziare con il carattere @ (come in @nome_della_variabile).
Per accedere ad un elemento di un array di scalari basta utilizzare la sintassi $_nome_del_array[indice]; quindi per accedere al 5 elemento dell'array @pluto si dovrà utilizzare: $pluto[4], tendendo conto che il primo elemento di un array ha indice 0.

 

Array associativi

Meritano una breve spiegazione gli array associativi, nei quali si può accedere ad ogni dato attraverso un indice: è possibile rappresentare, in prima istanza, un array associativo come una tabella nella quale la prima colanna rappresenta le chiavi di accesso ai dati, mentre la seconda colonna rappresenta il dato stesso. Vediamo una tabella e proviamo a vedere come tradurre il tutto in Perl:

1 GNU/Linux
2 BeOS
3 Windows NT
 Il nome di un array associativo è contrassegnato dal carattere speciale % (%nome_della_variabile).

Ecco come tradurre la struttura dati in Perl:

$tabella_so{1}= "GNU/Linux";
$tabella_so{2}= "BeOS";
$tabella_so{3}= "Windows NT";
Per accedere all'elemento con chiave 2 (BeOS) è sufficiente scrivere:
print $tabella_so{2}    # Scrive il valore BeOS
È interessante vedere come pur dovendo riferirsi all'intero array associativo con %nome_della_variabile, in questo caso %tabella_so, per riferirsi ad un singolo elemento dell'array si debba usare la sintassi $nome_del_array_associativo{elemento}. 

Espressioni regolari in Perl

Proprio perché il Perl è nato per essere un linguaggio che estraesse dati da file e li presentasse in forma diversa, la sua potenza nel trattare file di testo è realmente incredibile: ne sono un esempio le espressioni regolari.

Una expressione regolare è un pattern, un template, che deve corrispondere ad una stringa; il concetto di espressione regolare non è nuovo all'ambiente Un*x, programmi come Emacs, VI o grep usano espressioni regolari: se vogliamo ad esempio trovare nel nostro filesystem un file che contenga le lettere "unx" possiamo usare un comandino del genere:

find | grep unx
unx non rappresenta altro che l'E.R. da passare a grep perché lui ne cerchi un corrispondente.

Quante volte è capitato di trovarsi davanti ad una domanda alla quale di doveva rispondere con un Y o un N, formulata nel seguente modo:

Would you like to continue?
Le risposte plausibili possono essere:
    y

    Y

    yes

    Yes

    YES

    n

    N

    n

    No

    NO

10 risposte plausibili tutte da gestire: Perl semplifica il problema nel seguente modo, attraverso l'uso delle E.R.:
print "Continue?"       # Scrive continue a video ma NON va a capo
if (<STDIN> =~ /^[yY]/)         # Controlla se la risposta inserita dall'utente nello standard input
                                # inizia con una y o una Y
{
        # gestisce la risposta y
} else
        {
                # Gestisce la risposta n
        }
 

E il gioco è fatto, prima piccola magia del Perl. ;-)
Un'altra piccola magia: anfinger Una delle macchine che mi trovo ad amministrare è un server di posta elettronica di studenti di un università; il nome degli studenti non compare nel loro login name, e per cercare un utente con il cognome Rossi è necessario utilizzare il comando finger. Per svariate ragioni il finger è stato levato dalla macchina, anche per gli utenti che eseguono comandi da shell; a questo scopo ho creato A nice Finger di cui segue il listato: invocato con la sintassi indicata anfinger restituisce l'indirizzo di posta elettronica dello studente che ha il nome dato sulla riga di comando:

anfinger ignoti

Eccone il listato:
 
 

1 #!/usr/bin/perl
# ANFinger
##############################################################################
# Variabili per le installazioni differenti e per le successive modifiche    #
##############################################################################
2 $FILE_PASSWD=" /etc/passwd"; # questa variabile deve essere cambiata secondo le 
                             # impostazioni della macchina in cui viene usato 
                             # ANFinger
                          
3 $versione = "1.00";       # La versione attuale del programma
4 $notfound = 0 ;           # Inizializzo la variabile
              
5 if ($ARGV[0] eq "") {
6   print "Utilizzare anfinger <nome utente>\n";
7   exit;
}
8 $nome =~ tr/A-Z/a-z/;
9 print "\n\nANFinger $versione by Corrado Ignoti\n";
10 print "Risultati della ricerca effettuata con la chiave $ARGV[0]\n\n";
11 open (password, $FILE_PASSWD); # accedo al file passwd
12 while ($name = <password>) {
13    chop ($name);
14    @login = split (/:/, $name);
15    $login[4] =~ tr/A-Z/a-z/;
16    if ($login[4] =~ /$ARGV[0]/i) {
17       print "$login[4], e-mail: $login[0]\@$ENV{HOST}.$ENV{DOMAIN}\n";
       } else { 
       $notfound = $notfound + 1; 
      }
 }
18 close (password);
if ($notfound == 1) {
19      die "Non ci sono utenti per la chiave specificata\n\n";
}
if ($notfound > 1) {
     die "\n\nNon ci sono altri utenti per la chiave specificata\n\n"; 
}
Commentiamo brevemente il listato:

la riga 1 dice alla shell che il listato seguente deve essere interpretato attraverso il programma perl; nella riga 5 troviamo una cosa interessante: viene controllato se anfinger è stato invocato senza argomenti sulla linea di comando, il funzionamento di ARGV è simile a quello del C ( o meglio di Java), infatti $ARGV[0] (il primo elemento dell'array @ARGV) è il primo argomento passato sulla riga di comando dopo il nome del file.

la riga 8 è un espressione regolare che trasforma il contenuto della variabile $nome da maiuscolo a minuscolo, riassegnandolo alla variabile $nome stessa

la riga 11 accede al file /etc/passwd, mentre il ciclo while alla riga 12 scandisce sequenzialmente il file, l'istruzione alla riga 13, cancella l'ultimo carattere di una stringa; la cosa interessante è però l'istruzione alla riga 14, con la quale si forma l'array @login che contiene gli elementi di una riga del file passwd: ogni campo dell'array contiene un elemento diverso del file; per suddividere gli elementi si utilizza il carattere ``:'', infatti il file passwd è così strutturato:
 

nome:password:uid:gid:fullname:home/directory
l'array @login dopo l'operazione di split, risulterà formato da:

$login[0] = nome
$login[1] = password
$login[2] =  uid
.....
$login[4] = homedirectory

la riga 17 comunica i dati all'utente (si noti l'uso di \@ per visualizzare il carattere ``@'' e $ENV{HOST}.$ENV{DOMAIN} per la visualizzazione rispettivamente della variabile contenente il nome dell' host e del dominio).
 

Linux e il Perl

Inutile dire che qualsiasi distribuzione Linux, dalla più comune alla più ``esotica'', contiene i pacchetti necessari per avere l'interprete Perl funzionante sulla propria macchina.

Per iniziare: libri e link sul Perl

Learning Perl
Randal L. Schwartz foreword by Larry Wall
O'Reilly and Associates, Inc. 1994
ISBN 1-56592-042-2
Il libro scritto direttamente dall'autore del linguaggio, ottimo punto di partenza.
www.Perl.com
Un buon punto di partenza per trovare materiale ed informazioni sul Perl
Programming Perl, 2nd Edition
Larry Wall, Tom Christiansen & Randal L. Schwartz
O'Reilly and Associates, Inc 1996
ISBN 1-56592-149-6
Per approfondire la propria conoscenza del Perl
Perl by example
Ellie Quigley
Prentice Hall
copre con esempi molto chiari tutte le parti del perl (compresi OOP, CGI
ed interazione con il sistema), ed ha un CDROM con tutti i porting per i
vari sistemi operativi e dei programmi di esempio.

di Corrado Ignoti


[precedente] GIMP - Copertina - CDROM-edicola [successivo]