paper.gifioProgrammo N°5, Giugno 1997 ©Copyright DIEMME Editori

fire.gif

LE OPERAZIONI DI I/O SU FILE
Vediamo come il Perl possa garantire un efficace accesso ai file e al sistema operativo. Due funzioni che completano il linguaggio e ne fanno uno strumento di sviluppo molto versatile
Le operazioni di input/output su file richiedono l'uso di un "handlefile", ovvero un nome per identificare il file fisico presente su disco. L'handlefile, solitamente scritto in maiuscolo, può essere un handle aperto dalla funzione open, un handle predefinito oppure una variabile scalare che contiene l'handleflile da usare. I file handle predefiniti sono STDIN che indica lo standard input (la tastiera per default), STDOUT usato per la stampa su terminale e STDERR per stampare i messaggi di errore. Per leggere da un file si scrive il file handle tra parentesi angolari. Supponiamo di voler leggere e stampare il contenuto del file prova.txt nella directory corrente

open (FILE, "prova.txt");
while (<FILE>) {
  print $_;
}
close FILE;

La funzione open per default apre un file per la lettura e lo associa al file handle. Tuttavia per consentire altri tipi di accesso si possono aggiungere alcuni caratteri speciali all'inizio del nome del file. Per scrivere su un file si usa il prefisso > [open (FILE, ">prova.txt")], l'append si ottiene con >> mentre per aprire un file sia in lettura che in scrittura si usa +> . Un altro carattere speciale molto utile è il pipe |. In questo caso il nome del file è un comando del sistema operativo. Se usiamo il pipe davanti al comando si può inviare dell'output al comando stesso, così:

open (MAIL, "| mail -s "ciao" root);
print MAIL "come va?";
close MAIL;

mentre se il nome del file termina con | è possibile catturare l'output del comando usando le parentesi angolari

print "processi attivi\n";
open (PS, "ps |");
while (<PS>) {
  @ps = split (/\d:\d\d/);
  print "$ps[1]";
}
close PS;

Esistono infine molti operatori unari per eseguire test sui file. I più usati sono -r -w -x che rispettivamente verificano se un file è leggibile, scrivibile od eseguibile. Oppure -f -d che ritornano vero se il file è un file normale o una directory

unless (-f "prova.txt") {
  open (FILE, ">prova.txt");
  print FILE "questa è una prova\n";
  close FILE;
}

linea.gif
L'ACCESSO AL SISTEMA OPERATIVO
Il Perl consente di eseguire qualsiasi comando del sistema operativo, utilizzando uno dei tre metodi seguenti. Si può usare le funzione system passandole una stringa contenente proprio il nome del comando: system ("ls -l"). Tale funzione ritorna 0 sei il comando è stato eseguito con successo ed il codice di uscita viene memorizzato nella variabile speciale $? . Simile a system è la funzione exec che però non ritorna alcun valore. La funzione system a differenza di exec esegue prima un fork e attende il termine del processo figlio (il comando passato a system) per poi rientrare nel processo padre (lo script). Infine e possibile eseguire un comando racchiudendolo tra accenti gravi ` print `date`; In questo caso l'uso degli accenti consente di assegnare ad una variabile l'uscita del comando

$ora = `date | cut -b 12-19`;
print "ora esatta: $ora";

linea.gif
I DEFAULT
La lettura e la comprensione di uno script scritto da un guru del Perl il più delle volte risulta piuttosto laboriosa. Il motivo è molto semplice. Spesso per questioni di stile ed efficienza si scrive codice senza l'uso esplicito di variabili, abusando (a volte) della possibilità offerta da molte funzioni di usare variabili speciali o "implicite". Diamo un'occhiata al seguente esempio con cui è possibile estrarre il titolo di un documento html.

open (HTML, "file.html");
while (<HTML>) {
  if ( /<title>/i ) {
    s/<title>/<>/ig;
    s/<\/title>/<>/ig;
    @title = split(/<>/);
    last;
  }
}
print "titolo: $title[1]\n";
close HTML;

Nel ciclo while si inizia a leggere il file html. Se in una riga c'è il tag <title> lo si sostituisce con <>. Sostituiamo anche </title> e poi con la funzione split spezziamo la riga usando come separatore proprio <> . Verrà creato l'array @title il cui secondo elemento sarà il titolo della pagina html. Tutte queste operazioni vengono eseguite sulla variabile $_ che guarda caso contiene per dafault la riga letta da un file. L'uso di $_ e @ARGV è quindi noto, fissiamo ora la nostra attenzione su @_ . Questo array viene usato per passare gli argomenti alle subroutine.

sub somma {
  local ($a , $b) = @_;
  $a + $b;
}
print &somma(1, 2);

Per usare una nostra funzione bisogna quindi dichiararne il nome con sub e creare un insieme di variabili locale alla funzione con local. La funzione riceve i parametri per riferimento nell'array @_ e restituisce il valore calcolato nell'ultima espressione. Per chiamare una subroutine si usa il prefisso & prima del nome. Un altro default utile è $# che usato in un contesto di array contiene l'ultimo indice dell'array. Concludiamo con un esempio di riepilogo. Si tratta di uno script che permette l'invio di un file di testo ad una serie di indirizzi e-mail.

unless ($#ARGV == 1) {
  print "usage: sendall [subject] [file]\n";
  exit;
}
@email = ("email1", "email2", "email3");
foreach $email (@email) {
  system ("mail -s \"$ARGV[0]\" $email < $ARGV[1]");
}

Ovviamente basta sostituire le stringhe email1, email2 ecc con alcuni indirizzi e-mail veri e magari rendere il tutto più' robusto con alcuni controlli sugli errori.
linea.gif
PER APPROFONDIRE
Come sappiamo il Perl deve il suo successo ad Internet. I massimi autori di questo simpatico linguaggio hanno un sito ricco di informazioni utili per chi volesse approfondirne lo studio (www.perl.com). Per chi invece non ha tempo da perdere sul web può aiutarsi con il "Camel Book", nome scherzoso che Larry Wall, Tom Christiansen & company hanno addottato per "Programming Perl", uno dei manuali più aggiornati giunto da poco alla seconda edizione. Infine per chi non si accontenta proponiamo una visita alle Perl FAQ che l'università dell'Indiana raccoglie nel sito www.indiana.edu/iub.

fire.gif

Data creazione HTML: Febbraio 1998
Autore: Francesco Munaretto
E-mail: NoSpam@thank.you
exclaim.gif