PERL Cos’e’ PERL ? PracticalExtraction and Report Language oppure Pathological Eclectic Rubbish Lister ? Nato per assistere l’utente Unix per le comuni operazioni, troppo pesanti, troppo dipendenti dalla shell ma troppo complesse da codificare in C ... Linguaggio Interpretato con sintassi C-like, con elementi di C, Fortran, Basic, Pascal, Shell etc etc. Accetta la maggior parte dei comandi Unix. Accetta comandi sed e awk ... Ottimizzato per eleborare testi, ma anche per gestire numeri Correntemente molto usato per operazioni di amministrazione di sistema Scritto da Larry Wall (“A shell for C programmers”) Distribuito gratuitamente ( !) PERL scripts : Commenti => carattere # Informazione sul programma => Le istruzioni sono seguite da “ ;” Sulla prima riga # !/user/bin/perl 1 Tipi di dati in PERL Dati scalari, array, array associativi Numeri : rappresentazione interna solo doppia precisione Assegnazione : floating point, integer, stringhe C-like Delimitatori delle stringhe : accento singolo : per avere un carattere ‘ => \’ accento doppio : il backslash consente di inserire caratteri di controllo Caratteri di controllo : \n \r \t \f \b \v \a \e \007 \x7f newline return tab linefeed backspace tab verticale bell esc un valore ascii ottale un valore ascii hex \cC \\ \” \l \L \u \U \E un carattere di controllo (in questo caso control-C) backslash doppio accento il prossimo carattere e’ minuscolo tutte i prossimi caratteri sono minuscoli il prox carattere e’ maiuscolo tutti I prox caratteri sono maiuscoli termina \L o \U 2 Operatori Operatori aritmetici : + - * / ** % NB:Calcoli internamente in virgola mobile Operatori logici di confronto : tra numeri < <= > >= == != tra stringhe lt le gt ge eq ne NB : il confronto tra stringhe e’ diverso dal confronto tra numeri Operatori per stringhe : concatenazione : . ripetizione : x (es. “aaa”.”bbb” = aaabbb) (es. ‘a’x3 = aaa) Conversione tra numeri e stringhe. Es. “F”.(“ 43” + 6) = “F49” 3 Variabili scalari Case sensitive Il valore di una variabile ‘nomevar’ e’ sempre identificato con $nomevar Operatori di assegnazione binaria : += *= .= Autoincremento, autodecremento: ++$a $a++ Operatore chop(argomento) : elimina l’ultimo carattere dell’argomento. Ritorna il carattere eliminato Inserimento di variabili scalari in stringhe delimitate da “” Es. $a=”bla bla $b bla bla” ; Se la variabile inserita viene seguita subito da testo, si puo’ usare il delimitatore {} Es. $a=”blabla${b}bla” ; stesso risultato di $a=”blabla$b”.”bla” ; Lettura dalla tastiera : stringa <STDIN> Es. $a=<STDIN> ; chop(a) ; oppure chop($a=<STDIN>) ; Scrittura sullo standard output : print Es. print(“blabla\n”) ; oppure print ”blabla\n” ; 4 Array in PERL Non ci sono limiti sul numero di elementi Variabili di tipo Array : individuate con il carattere @ Es. @a=(1,2,3) ; @a=1 ; # array di un solo elemento @b=@a ; @a=(“uno”, “due”, “tre”) ; @b=(1,2,@a,3) ; # @b contiene (1,2,”uno”,”due”,”tre”,3) Uso di variabili nell’array. Es : ($a, $b, $c) = (1,2,3) ; ($a, $b) = ($b, $a) ; ($d, @z) = ($a, $b, $c) ; ($e, @z)=@z ; #inizializza le variabili $a $b $c #inverte #risultato : $d=$a, @z=($b, $c) #risultato : $e=$b, @z=($c) Se il numero di elementi non corrisponde : scarto elementi o undefined Assegnazione scalare=array : la var scalare contiene il numero di elementi Es : @a=(1,2,3) ; $b=@a ; #risultato : la var b contiene 3 Ma : ($b) = @a ; # la var b contiene il primo elemento di @a 5 Accesso agli elementi di un array Gli elementi di un array sono indiciati da 0 Es : @a=(1, 2, 3) ; $b=$a[0] ; #$b contiene 1 $a[0]=4 ; #@a = (4,2,3) $a[1]++; $a[2] += 4; L’array puo’ essere riferito in parti con una notazione speciale: Es : @b=@a[0,1] ; # equivale a @b=($a[0], $a[1]) ; @a[0,1]=(x,y) ; # come @a=(x,y) @b=(1,2,3)[2,3]; # come @x=(1,2,3) @b=@x[2,3] $x=0 ; $y=1 ; @b=(1,2,3)[$x,$y] ; @z=($x,$y) ; @b=(1,2,3)[@z] ; Accedere ad un elemento non definito ritorna undef ; assegnare un elemento non definito estende l’array Massimo indice di un array : $#a 6 Operatori per array push() e pop() : aggiungono e tolgono elementi dal lato destro dell’array. Es push(@a,$x) ; # come @a = (@a, $x) $old=pop(@a) ; push(@a,$x,$y,$z) ; shift() e unshift() : tolgono e aggiungono elementi dal lato sinistro dell’array Es. unshift(@a, $x) ; #come @a=($x,@a) $x=shift(@a) ; #come ($x,@a)=@a reverse() : inverte l’ordine degli elemeti di un array sort() : Es : @a=sort(@a) ; ordina un array in senso ascendente. chop() : se applicato ad un array, elimina l’ultimo elemento. Lettura da tastiera con <STDIN> Es. : @a=<STDIN> ; #legge dallo standard input ogni riga in un elemento dell’array. Termina all’EOF (ctrl-D) Inserimento di elementi di array in variabili: Es. @a=(1,2,3) ; $b=”bla bla $a[1] bla” ; $b=”bla bla @a bla” ; $b=”blabla @a[1,2] bla” ; 7 Strutture di controllo in PERL Test: if(espressione){ istruzioni ; }else { istruzioni ; } if(espressione) { istruzioni ; } elsif (espressione) { istruzioni ; } elsif(espressione) { ... } NB : se l’espressione e’ una stringa di singoli caratteri, l’espressione e’ valutata come segue : se “0” => falso . Se non “0” => vero. Es . 0 “0” falso “0” falso 1-1 0 “0” falso “00” vero “” falso unless : realizza la parte else dell’if : unless(espressione){ istruzioni ; } 8 Strutture di controllo in PERL while/until while(espression){ istruzioni ; } until(espressione){ istruzioni ; } for for(iniziale ; test ; incremento) istruzioni; foreach $varloop: la variabile di loop e’ un riferimento ad ogni elemento dell’array. L’array puo’ essere modificato. Se non indico la variabile => variabile implicita $_ Es. foreach $i (@array) { istruzioni ; } 9 Array associativi Collezione di dati scalari, individuati dal valore delle chiavi. Indicati con %nome Es: %a=(“a”, dato_a, “b”, dato_b, “c”, dato_c); Accesso agli elementi di %a: Es. print $a{“a”}; print $a{“b”}; $b=$a{$chiave}; Inizializzazione elemento per elemento: $a{“a”} = “dato_a”; $a{“b”} = “dato_b”; Operatori per gli array associativi keys(): ritorna la lista di tutte le chiavi Es: @lista = keys(%a); # ritorna (“a”, “b”, “c”); foreach $key (keys(%a)){ print “alla chiave $key corrisponde $a{$key}” } # stampa la coppia chiave/valore each() ritorna la coppia (chiave, dato) Es. while( ($x,$y) = each(%a)) { Print “$x $y”; } delete cancella un elemento dell’array associativo tramite la chiave Es. delete $a(“a”); 10 Input/Output Lettura da <STDIN> Es. $a = <STDIN> #legge una linea @a = <STDIN> #legge tutte le linee fino a ^d while(<STDIN>){ #legge in $_ chop; #agisce su $_ # … elabora $_ } Operatore diamante < > : come STDIN ma legge una riga alla volta dai file forniti come argomenti dello script. NB: i nomi vengono prelevati dall’array @ARGV Es.: script ‘prova’ #!/usr/local/bin/perl while(<>) { print $_ } prova file1 file2 … Uscita su STDOUT con print. Es. $a = print(“blabla \n ») ; #ritorna vero o falso Print(“%s %d %f\n”, $a, $b, $c); 11 Espressioni regolari in PERL Racchiuse tra / / Es. funzione grep #!/usr/local/bin/perl while(<>){ if(/er/){ Print”$_”; } } Operatore di match =~ Applica una espressione regolare ad una variabile che non sia $_ Es. $a=”blablabla”; if($a =~ /^b/){ print $a #stampa $a se la stringa inizia con b } print “continuare? (S/s o N/n)” if(<STDIN> =~ /^[Ss]( { print “hai risposto si!” } Caratteri maiuscoli o minuscoli (ignora il case) con l’opzione i: /er/i 12 Inserimento di variabili: Una ER puo’ contenere variabili. Le variabili vengono espanse prima di considerare eventuali caratteri speciali. Es. $a=”abc def ghi”; print “scrivi una parola di 3 caratteri”; $b=<STDIN>; chop($b); if($a =~ /$b/){ print “trovato $b in $a\n”; } else { print “non trovato\n”; } Sostituzione in PERL: s/old-ER/new-ER/ Es. $_=”abc def ghi”; s/abc/xyz/g; #tutte le stringhe /abc/ vengono sostituite $a=”abc def ghi”; $a =~ s/abc/xyz/g; Operatore split(espressione regolare , stringa) : ritorna un vettore formato dalle parti della stringa che NON corrispondono alla ER Es. $a=”a:b:c:d”; @b=split(/:/, $a); # @b contiene (a, b, c ,d) @b=split(/er/); # in questo caso la stringa e’ $_ Operatore join($glue, @lista): riunisce gli elementi della lista attraverso $glue in una stringa Es. $a = join(“:”, @b); #ricostruisce la stringa precedente 13 Funzioni in PERL Il programmatore puo’ definire delle subroutine nella forma sub nome{ Istruzioni; } Le subroutine sono SOLO globali Chiamata di subroutine: &nome La subroutine ritorna l’ultimo valore calcolato Es. sub somma{ $a+$b; } $a=2; $b=3; $c=&somma; Valori ritornati da un array: sub lista{ ($a, $b); } $a=2; $b=3; @c=lista; 14 Gli argomenti di una subroutine sono disponibili all’interno della subroutine come array locale alla subroutine chiamato @_ Es. sub somma{ $_[0] + $_[1]; } print &somma(2, 3); Gli argomenti passati possono essere illimitati. Es. somma di elementi sub somma{ $x=0; foreach $i (@_){ $x += $i; } $x; # ultima espressione calcolata } $a = &somma(1,2,3,….,n); Definizione di variabili locali: operatore local() Es. sub somma{ local($a); local($i); #oppure local($a,$b); $a=0; foreach $i (@_) { $a += $i; } $a; } 15 Es. Lista di tutti gli elementi maggiori di A: sub somma{ local($n,@a); ($n,@a) = @_; local(@b); for($i=1;$i<$n; $i++){ if($a[$i]> A) push(@b, $a[$i]); } @b; } @a=&somma(100,@lista); oppure sub somma{ local($n,@a); ($n,@a) = @_; local(@b); foreach $_ (@a){ if($_ > A) push(@b, $_); } @b; } @a=&somma(100,@lista); Inizializzazione delle variabili locali: local($n, @a) = @_; oppure local($n) = 0; 16 Gestione dei file in PERL Gestione dei file attraverso i file handle Apertura di un file handle: open(nome file handle, “nome file”); o open ritorna vero o falso o per aprire in scrittura: open(OUT, “>nome file”); o aggiungere al file: open(OUT,”>>nome file”); o apertura in lettura: open(IN,”nome file”); Operatore die(“…”): scrive il messaggio e poi esce dal processo Es. unless(open(OUT,”>file”)){ print(“errore\n”); } else{ print(“ok\n”); #resto del programma; } diventa: unless(open(OUT,”>file”)){ die(“errore\n”); } else{ print(“ok\n”); #resto del programma; } oppure: open(OUT,”>file”) || die(“errore\n”); 17 Lettura file: open(IN, “file”); while(<IN>){ chop; print “linea letta= $_ \n”: } close(IN); Copia file: open(IN, “file_in”); open(OUT, “>file_out”); while(<IN>){ chop; print(OUT, $_); } close(IN); close(OUT); Test sui file: -r -w -x -o -R -W -X -O -e file leggibile file eseguibile file o directory eseguibile appartiene all’utente leggibile dall’utente reale, non effettivo scrivibile dall’utente reale eseguibile dall’utente reale appartiene all’utente reale il file esiste 18 -z -s -f -d -l -s -p -b -c -u -g -k -t -T -B -M -A -C il file esiste ma ha dimensione nulla esiste ed ha dimensione non nulla file regolare direttorio link simbolico socket pipe con nome (fifo) file speciale a blocchi file speciale a caratteri il file o directory ha il bit setuid settato bit setgid settato sticky bit settato file testo file binario tempo dall’ultima modifica in giorni tempo dall’ultimo accesso in giorni tempo dall’ultima modifica dell’inode in giorni Operatore stat(file handle) : ritorna informazioni dettagliate sui file. Es: ($dev, $ino, $mode, $nlink, $UID, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat(handle); Per selezionare le informazioni: Operatore lstat(handle): ($uid, $gid) = (stat(“handle”))[4,5]; ritorna informazioni dettagliate su un link simbolico 19 Gestione delle directories Operatore chdir: chdir(“directory”) || die Espansione degli argomenti (globbing): lista dei file corrispondenti alla espansione di *: @a = <*>; @a = <path*>; Es. while($b = <*>) { print “$b”; } Operatori opendir/closedir: gestione delle directory handle: opendir(ETC,”/etc”) || die(“errore\n”); Operatore readdir(handle) : ritorna un nome file ($a=readdir) o tutti i nomi file (@a=readdir) contenuti nella directory Es. nomi in ordine alfabetico. opendir(ETC,”/etc”) || die; foreach $a (sort readdir(ETC)){ print “$a\n”; } closedir(ETC); 20 Gestione file in PERL Cancellazione: unlink(nome). Ritorna il nr di file cancellati Es. unlink(“nomefile”); unlink(“file1”, “file2”, “file3”); unlink(<*.txt>); foreach $a (<*.txt>) { unlink($a) || die; } foreach (<*.txt>){ unlink || die(“errore $_ \n”); } Operatore rename($old, $new); Operatore link, symlink: rinomina file. introduce un link ad un file Es. Link(“old”,”new”)||die; #hard link Symlink(“old”, “new”) || die; #link simbolico Operatore mkdir(): crea subdirectories Es. Mkdir(“nomedir”, 0777); Operatore rmdir: Es. Rmdir(“nomedir”); cancella subdirectories 21 Operatore chmod() modifica i permessi del file; ritorna il nr di file modificati con successo Es. $a=chmod(0666,”nomefile”); Foreach $file (“nome1”, “nome2”){ Unless (chmod(0666, $file)) { Print “errore nella modifica dei permessi!!\n” } } Operatore chown: modifica proprietario/gruppo Es. chown(UID, GID, “file”); : # se 3290 = Pinco e 15006 = calcolat, la stessa operazione di chown Pinco nome1 nome2 e chrpp calcolat nome1 nome2 Chown(3290, 15006, “nome1”, “nome2”); Operatore utime(ultimo accesso, ultima modifica, files): modifica I tempi Tempi associati ad un file: data ultimo accesso, data ultima modifica, data ultima modifica dell’inode Usando l’operatore time (ritorna il tempo corrente): $a=time - 20*60; utime($a, $a, “nome_file1”, “nome_file2”, …); # 20 minuti da ora # i file indicati sono aggiornati a 20 minuti fa 22 Gestione processi in PERL Creazione processi con la istruzione system; ritorna 0 se l’operazione ha avuto successo, altrimenti 1: system(“comando di shell”) && die; system(“comando1; comando2 > filek&”) && die; system(“comando > file”) && die; Creazione processi tramite gli accenti singoli ` `. NB: lo standard input/output del comando ` ` sono ereditati da PERL Es. $a = “data attuale = “ . `date`; @a = `who`; Creazione processi tramite file handle: Es. Open(HANDLE, “who|”); @a = <HANDLE>; close(HANDLE); #lettura open(HANDLE, “|cat”); #scrittura print(HANDLE,”stringa da stampare con cat”); close(HANDLE); 23 Creazione processi con istruzioni fork/exec/wait: crea un clone del processo corrente. Fork ritorna 0 al figlio !0 al padre Es. If(fork){ Print “sono il padre”; } else{ print “sono il figlio”; exec(“date”); } unless (fork) { exec(“date”); } wait; # sono qui perche’ fork ritorna 0 Uscita da un processo con exit; Variabile d’ambiente: l’ambiente viene messo nell’array associativo %ENV Es. for $a (sort keys %ENV){ # elenca le variabili d’ambiente Print “$a = $ENV{$a}\n”; } $oldpath=$ENV(“PATH”); # modifica le variabili d’ambiente $ENV(“PATH”) = “ bla nuovo PATH bla”; … $ENV(“PATH”) = $oldpath; 24 Sommario delle operazioni sui processi: system() `` STDIN ereditato “ STDOUT ereditato STDOUT catturato come stringa STDERR ereditato “ Atteso! Atteso! Open() come output Connesso al file handle STDOUT ereditato STDERR ereditato Atteso all’istante di close Open() come input STDIN ereditato STDOUT connesso STDERR ereditato Atteso all’istante di close Fork, exec, Wait STDIN selezionato dall’utente STDOUT selezionato dall’utente STDERR selezionato dall’utente Selezionato dall’utente 25 Gestione Segnali in PERL Generazione di segnali: kill (segnale, PIDs); segnale numero o mnemonico. Posso inviare segnali a piu’ PID – separati da virgola Cattura di segnali: array associativo %SIG: Es. $SIG{‘INT} = ‘subroutine_name’; $SIG{‘INT’} = ‘DEFAULT’; sub subroutine_name{ istruzioni; … } 26 Conversione di altri linguaggi in PERL Semanticamente. PERL e’ un sovrainsieme di awk, ma non e’ sintatticamente compatibile con awk a2p per la conversione meccanica Similmente, semanticamente. PERL e’ un sovrainsieme di sed, ma non e’ sintatticamente compatibile con sed s2p per la conversione meccanica Esistono convertitori automatici per shell script? NO: la maggior parte delle cose non sono realizzate dallo script: programmi esterni, confronto con numeri o stringhe etc. => non si guadagna niente! 27