NOME |
perlfunc - Le funzioni integrate in Perl
Le funzioni in questa sezione possono comparire come termini
in una espressione. Esse cadono in due categorie principali:
operatori di lista e operatori unari con nome.
La differenza consiste nella relazione di precedenza con una
virgola che segue. (Consultate la tabella delle precedenze in the perlop manpage).
Gli operatori di lista prendono più di un argomento,
mentre gli operatori unari non accettano mai più di un argomento.
Quindi, la virgola termina l'argomento di un operatore unario, ma separa
semplicemente gli argomenti di un operatore di lista.
Un operatore unario solitamente fornisce un contesto scalare
al suo argomento, mentre un operatore di lista può conferire
sia un contesto scalare che uno di lista ai suoi argomenti.
Se conferisce entrambi i contesti, allora gli argomenti
scalari verranno per primi, seguiti dall'argomento lista.
(Va notato che ci può essere uno solo di tali argomenti).
Per esempio, splice()
ha tre argomenti scalari seguiti
da una lista, mentre gethostbyname()
ha quattro argomenti scalari.
Nelle descrizioni della sintassi che seguono, gli operatori di lista che si aspettano una lista (e che forniscono un contesto di lista agli elementi della lista) vengono mostrati con LISTA come argomento. Tale lista può essere costituita da una combinazione qualunque di argomenti scalari o valori di lista; i valori di lista saranno inclusi nella lista come se ogni singolo elemento fosse interpolato in quel punto, formando un valore di lista unico, più lungo. Delle virgole dovrebbero separare gli elementi della LISTA.
Ogni funzione dell'elenco sottostante può essere usata o meno con parentesi attorno ai propri argomenti. (La descrizione della sintassi omette le parentesi). Se usate le parentesi, la semplice regola (benché talvolta sorprendente) è questa: sembra una funzione, dunque è una funzione, e la precedenza non importa. Altrimenti è un operatore di lista o un operatore unario, e allora la precedenza conta. Ed uno spazio vuoto tra la funzione e la parentesi aperta non conta, quindi a volte dovete stare attenti:
print 1+2+4; # Stampa 7. print(1+2) + 4; # Stampa 3. print (1+2)+4; # Anche questo stampa 3! print +(1+2)+4; # Stampa 7. print ((1+2)+4); # Stampa 7.
Se lanciate Perl con lo switch -w, allora vi può avvertire a questo proposito. Per esempio, la terza linea produce:
print (...) interpreted as function at - line 1. Useless use of integer addition in void context at - line 1
[print (...) è interpretato come funzione alla linea 1. Utilizzo inutile di una addizione intera in un contesto vuoto alla linea 1, NdT]
Un esiguo numero di funzioni non accetta alcun argomento, e
quindi non funziona né come operatore di lista né
come operatore unario. Sono incluse in questo gruppo funzioni come
time
e endpwent
. Per esempio, time+86_400
vuol dire sempre
time() + 86_400
.
Per le funzioni che possono essere usate in un contesto scalare o di lista, un fallimento non bloccante viene generalmente indicato restituendo il valore indefinito in un contesto scalare, e la lista nulla in un contesto di lista.
Ricordate la seguente importante regola: Non esiste alcuna regola che correla il comportamento di un'espressione in un contesto di lista al suo comportamento in un contesto scalare, o viceversa. Potrebbe comportarsi in due maniere totalmente differenti. Ogni operatore e ogni funzione decidono quale genere di valore sia più appropriato restituire in un contesto scalare. Alcuni operatori restituiscono la lunghezza della lista che sarebbe stata restituita in un contesto di lista. Alcuni operatori restituiscono il primo valore nella lista. Alcuni restituiscono l'ultimo. Alcuni operatori restituiscono il conto delle operazioni eseguite con successo. In generale, fanno quello che volete, a meno che non vogliate la consistenza.
Un array dotato di nome, in un contesto scalare è piuttosto
differente da quella che a prima vista potrebbe apparire come una lista in un
contesto scalare. Non potete fare in modo che una lista come (1,2,3)
si trovi in un contesto scalare, poiché il compilatore conosce il
contesto al momento della compilazione. Genererebbe l'operatore scalare virgola,
non l'operatore virgola che costruisce una lista.
Ciò significa che quella non era una lista nemmeno in partenza.
In generale, le funzioni Perl che fungono da wrapper [involucro, interfaccia
tra un programma ed un altro, NdT] per le chiamate di sistema che hanno lo
stesso nome (come chown(2), fork(2), closedir(2), ecc.) restituiscono tutte
vero quando hanno successo e undef
in caso contrario, come viene solitamente
menzionato nelle descrizioni che seguono. Ciò differisce dall'interfaccia
C, che restituisce -1
in caso di fallimento. Le eccezioni a questa regola sono
wait
, waitpid
e syscall
. Le chiamate di sistema inoltre impostano la variabile
speciale $!
in caso di fallimento. Altre funzioni non lo fanno,
se non accidentalmente.
Ecco le funzioni del Perl (incluse certe cose che assomigliano a funzioni, come alcune parole chiave e operatori dotati di nome) ordinate per categoria. Alcune funzioni appaiono in più di una posizione.
chomp
, chop
, chr
, crypt
, hex
, index
, lc
, lcfirst
,
length
, oct
, ord
, pack
, q/STRINGA/
, qq/STRINGA/
, reverse
,
rindex
, sprintf
, substr
, tr///
, uc
, ucfirst
, y///
m//
, pos
, quotemeta
, s///
, split
, study
, qr//
abs
, atan2
, cos
, exp
, hex
, int
, log
, oct
, rand
,
sin
, sqrt
, srand
pop
, push
, shift
, splice
, unshift
grep
, join
, map
, qw/STRINGA/
, reverse
, sort
, unpack
delete
, each
, exists
, keys
, values
binmode
, close
, closedir
, dbmclose
, dbmopen
, die
, eof
,
fileno
, flock
, format
, getc
, print
, printf
, read
,
readdir
, rewinddir
, seek
, seekdir
, select
, syscall
,
sysread
, sysseek
, syswrite
, tell
, telldir
, truncate
,
warn
, write
pack
, read
, syscall
, sysread
, syswrite
, unpack
, vec
-X
, chdir
, chmod
, chown
, chroot
, fcntl
, glob
,
ioctl
, link
, lstat
, mkdir
, open
, opendir
,
readlink
, rename
, rmdir
, stat
, symlink
, sysopen
,
umask
, unlink
, utime
caller
, continue
, die
, do
, dump
, eval
, exit
,
goto
, last
, next
, redo
, return
, sub
, wantarray
caller
, import
, local
, my
, our
, package
, use
defined
, dump
, eval
, formline
, local
, my
, our
, reset
,
scalar
, undef
, wantarray
alarm
, exec
, fork
, getpgrp
, getppid
, getpriority
, kill
,
pipe
, qx/STRINGA/
, setpgrp
, setpriority
, sleep
, system
,
times
, wait
, waitpid
do
, import
, no
, package
, require
, use
bless
, dbmclose
, dbmopen
, package
, ref
, tie
, tied
,
untie
, use
accept
, bind
, connect
, getpeername
, getsockname
,
getsockopt
, listen
, recv
, send
, setsockopt
, shutdown
,
socket
, socketpair
msgctl
, msgget
, msgrcv
, msgsnd
, semctl
, semget
, semop
,
shmctl
, shmget
, shmread
, shmwrite
endgrent
, endhostent
, endnetent
, endpwent
, getgrent
,
getgrgid
, getgrnam
, getlogin
, getpwent
, getpwnam
,
getpwuid
, setgrent
, setpwent
endprotoent
, endservent
, gethostbyaddr
, gethostbyname
,
gethostent
, getnetbyaddr
, getnetbyname
, getnetent
,
getprotobyname
, getprotobynumber
, getprotoent
,
getservbyname
, getservbyport
, getservent
, sethostent
,
setnetent
, setprotoent
, setservent
gmtime
, localtime
, time
, times
abs
, bless
, chomp
, chr
, exists
, formline
, glob
,
import
, lc
, lcfirst
, map
, my
, no
, our
, prototype
,
qx
, qw
, readline
, readpipe
, ref
, sub*
, sysopen
, tie
,
tied
, uc
, ucfirst
, untie
, use
* - sub
era una parola chiave in perl4, ma in perl5 è un operatore,
che può essere usato nelle espressioni.
dbmclose
, dbmopen
Perl è nato su Unix e dunque può accedere a tutte le normali chiamate di sistema Unix. In ambienti non-Unix, le funzionalità di alcune di queste chiamate potrebbe non essere disponibile, oppure i dettagli potrebbero essere un po' diversi. Le funzioni Perl influenzate da questo aspetto sono:
-X
, binmode
, chmod
, chown
, chroot
, crypt
,
dbmclose
, dbmopen
, dump
, endgrent
, endhostent
,
endnetent
, endprotoent
, endpwent
, endservent
, exec
,
fcntl
, flock
, fork
, getgrent
, getgrgid
, gethostbyname
,
gethostent
, getlogin
, getnetbyaddr
, getnetbyname
, getnetent
,
getppid
, getpgrp
, getpriority
, getprotobynumber
,
getprotoent
, getpwent
, getpwnam
, getpwuid
,
getservbyport
, getservent
, getsockopt
, glob
, ioctl
,
kill
, link
, lstat
, msgctl
, msgget
, msgrcv
,
msgsnd
, open
, pipe
, readlink
, rename
, select
, semctl
,
semget
, semop
, setgrent
, sethostent
, setnetent
,
setpgrp
, setpriority
, setprotoent
, setpwent
,
setservent
, setsockopt
, shmctl
, shmget
, shmread
,
shmwrite
, socket
, socketpair
,
stat
, symlink
, syscall
, sysopen
, system
,
times
, truncate
, umask
, unlink
,
utime
, wait
, waitpid
Per maggiori informazioni riguardanti la portabilità di queste funzioni, consultate the perlport manpage ed altra documentazione disponibile specifica per una data piattaforma.
$_
; fa eccezione -t
, che utilizza STDIN.
A meno di indicazione contraria, restituisce 1
per indicare la verità
della condizione verificata, e ''
in caso di falsità, mentre
restituisce un valore non definito se il file non esiste. A dispetto
della stranezza dei nomi, valgono le stesse regole di precedenza di ogni
altro operatore unario, e l'argomento può essere racchiuso fra parentesi
come per qualsiasi altro operatore. L'operatore può essere uno qualsiasi
fra quelli seguenti:
-r Il file e` leggibile da parte del uid/gid effettivo. -w Il file e` scrivibile da parte del uid/gid effettivo. -x Il file e` eseguibile da parte del uid/gid effettivo. -o Il file appartiene al uid effettivo.
-R Il file e` leggibile da parte del uid/gid reale. -W Il file e` scrivibile da parte del uid/gid reale. -X Il file e` eseguibile da parte del uid/gid reale. -O Il file appartiene al uid reale.
-e Il file esiste. -z Il file ha dimensione zero (e` vuoto). -s Il file ha dimensione diversa da zero (restituisce la dimensione in byte).
-f Il file e` un file vero e proprio [non una directory ma un link, NdT] -d Il file e` una directory. -l Il file e` un link simbolico. -p Il file e` una named pipe (FIFO), o la Filehandle e` una pipe. -S Il file e` un socket. -b Il file e` un file speciale per una periferica a blocchi. -c Il file e` un file speciale per una periferica a caratteri. -t La filehandle e` aperta su una tty [per esempio un terminale, NdT].
-u Il file ha il bit setuid impostato. -g Il file ha il bit setgid impostato. -k Il file ha lo sticky bit impostato.
-T Il file contiene un testo ASCII (viene determinato in maniera euristica). -B Il file e` un file binario (opposto di -T).
-M Orario di avvio dello script meno l'orario di ultima modifica del file, in giorni. -A Come sopra, ma con l'orario di ultimo accesso al file. -C Come sopra, ma per l'orario di ultima modifica del inode (su Unix, potrebbe essere diverso su un'altra piattaforma).
Esempio:
while (<>) { chomp; next unless -f $_; # ignora i file speciali #... }
L'interpretazione degli operatori che verificano i permessi dei file
-r
, -R
, -w
, -W
, -x
e -X
è basata di default
solamente sullo stato del file e sul valore degli uid e gid dell'utente.
Ci potrebbero essere altre ragioni per cui vi potrebbe risultare
impossibile leggere, scrivere o eseguire il file. Tali ragioni
potrebbero essere ad esempio controlli di accesso su un filesystem di
rete, ACL (Access Control lists, [liste di controllo di accesso, NdT]),
filesystem accessibili in sola lettura, e formati eseguibili non
riconosciuti.
Va notato inoltre che, per il superuser sui filesystem locali, gli
operatori -r
, -R
, -w
e -W
restituiscono sempre 1, e -x
e
-X
restituiscono 1 se uno qualsiasi dei bit di esecuzione è
impostato. Gli script eseguiti dal superuser devono perciò
utilizzare la funzione stat()
per determinare il reale stato del file,
oppure devono temporaneamente impostare il loro uid effettivo ad un valore
diverso.
Se state usando le ACL, c'è una direttiva chiamata filetest
che
può produrre risultati più accurati di quelli ottenibili con
un semplice stat(). Con la direttiva use filetest 'access'
in uso, gli
operatori sopra citati verificheranno i permessi utilizzando la famiglia di
chiamate a sistema operativo access(). Va notato inoltre che quando questa
direttiva è in uso, gli operatori -x
e -X
potrebbero restituire il
valore booleano vero anche se i bit di esecuzione non sono impostati sui
file (così come potrebbe accadere anche se nessun ulteriore permesso di
eseguibilità è stato garantito da una ACL). Queste stranezze sono
dovute alle definizioni del sistema operativo su cui operano. Leggete la
documentazione di filetest
per avere maggiori informazioni.
Va notato che -s/a/b/
non è la negazione di una sostituzione.
Scrivere -exp($pippo)
funziona sempre come ci si aspetta che faccia, solo le
lettere singole che seguono un segno meno sono interpretate come test sui file.
Gli operatori -T
e -B
funzionano nel modo seguente. Il primo blocco
(più o meno) del file viene esaminato alla ricerca di caratteri
strani come ad esempio codici di controllo o caratteri con il bit alto
impostato. Se vengono individuati troppi caratteri strani (>30%),
l'operatore -B
restituisce vero; altrimenti restituirà vero
l'operatore -T
. Inoltre, un qualunque file che contiene un carattere
``null'' nel primo blocco è considerato binario. Se -T
o -B
vengono
usati su un filehandle, viene esaminato il buffer di IO corrente, e non
il primo blocco. Sia -T
che -B
restituiscono il valore booleano
vero su un file vuoto, o su un filehandle che è arrivata alla fine del
file. Poiché eseguendo -T
deve avvenire una lettura del file, nella
maggior parte delle occasioni ha senso eseguire un -f
sul file come
prima cosa, come ad esempio in next unless -f $file && -T $file
.
Se a uno qualsiasi dei test sui file (o uno fra gli operatori stat
e
lstat
) viene richiesto di esaminare lo speciale filehandle costituito
da un trattino di sottolineatura ``_'', verrà utilizzata il risultato
della chiamata stat effettuata dall'ultimo test sul file o operatore stat,
in modo da risparmiare una chiamata a sistema operativo. (Questo non
vale per -t
, e dovrete ricordare anche che lstat()
e -l
memorizzeranno il risultato della chiamata stat relative al link
simbolico stesso, e non quelle relative al file puntato dal link).
(Inoltre, se il buffer della chiamata stat è stato precedentemente
riempito da una chiamata lstat
, -T
e -B
verranno reimpostati al
valore restituito da stat _
).
Esempio:
print "Si puo` fare.\n" if -r $a || -w _ || -x _;
stat($filename); print "Leggibile\n" if -r _; print "Scrivibile\n" if -w _; print "Eseguibile\n" if -x _; print "Setuid\n" if -u _; print "Setgid\n" if -g _; print "Sticky\n" if -k _; print "Testo\n" if -T _; print "File binario\n" if -B _;
abs()
usa $_
.
Su sistemi che, sui file, supportano un flag chiuso-su-esecuzione, tale flag sarà impostato per il più recente descrittore di file aperto, come stabilito dal valore di $^F. Consultate $^F in the perlvar manpage.
$_
. (Su alcune
macchine, sfortunatamente, il tempo trascorso può essere inferiore
o superiore fino a un secondo rispetto al numero specificato
a causa del sistema con cui vengono contati i secondi, e lo scheduling
[programmazione, NdT] dei processi può ulteriormente ritardare
la consegna del segnale).
Può essere in esecuzione un solo timer alla volta. Ciascuna
chiamata disabilita il timer definito in precedenza, ed un argomento
di 0
può essere fornito per cancellare il timer precedente
senza avviarne uno nuovo. Il valore restituito rappresenta
il tempo rimanente sul timer precedente.
Per intervalli di una granularità più fine, inferiore
al secondo, potete utilizzare la versione a quattro argomenti di
select(), fornita da Perl, lasciando i primi tre argomenti non
definiti. In alternativa potreste essere in grado di servirvi
dell'interfaccia syscall
per accedere a setitimer(2)
se il vostro
sistema supporta ciò. Anche il modulo Time::HiRes (da CPAN, e
parte della distribuzione standard a partire da Perl 5.8) potrebbe
risultare utile.
Solitamente è un errore mischiare chiamate alarm
e sleep
.
(nel vostro sistema, sleep
potrebbe essere essere implementata
internamente con alarm
)
Se volete utilizzare alarm
per far scadere una chiamata di sistema,
dovrete utilizzare una coppia eval
/die
. Non potete contare
sul fatto che alarm faccia fallire la chiamata di sistema impostando
$!
a EINTR
, poiché in alcuni sistemi Perl imposta i gestori
dei segnali in modo che riavviino le chiamate di sistema. La soluzione
che prevede l'uso di eval
/die
funziona sempre, a meno degli avvertimenti
indicati in Signals in the perlipc manpage [``Segnali'', NdT].
eval { local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n richiesto alarm $timeout; $nletto = sysread SOCKET, $buffer, $dimensione; alarm 0; }; if ($@) { die unless $@ eq "alarm\n"; # propaga gli errori inattesi # scaduto } else { # non scaduto }
Per maggiori informazioni consultate the perlipc manpage.
Per ottenere la tangente, potete usare la funzione Math::Trig::tan
,
o la consueta relazione:
sub tan { sin($_[0]) / cos($_[0]) }
Si noti che atan2(0, 0) non è ben definito.
undef
in ed imposta $!
(errno).
Su alcuni sistemi (in generale basati su DOS e Windows) binmode()
è
necessario quando non state lavorando con file di testo. Per una questione di
portabilità è una buona idea usarlo sempre, se richiesto,
e non usarlo mai quando non è richiesto. Le persone possono anche
impostare i loro input/output per essere, di default, Unicode codificato UTF-8, e
non dei byte.
In altre parole: indipendentemente dal sistema operativo, usate binmode()
sui file binari, come ad esempio immagini.
Se STRATO è presente, è una stringa singola, ma può contenere direttive multiple. Le direttive alternano il comportamento del filehandle. Quando STRATO è presente, usare binmode sui file di testo ha un senso.
Se STRATO viene omesso o specificato come :raw
, il filehandle viene reso adatto a
trasferire dati binari. Ciò include la disabilitazione di tutte le eventuali
conversioni di CRLF, e la marcatura dei dati come byte (e non caratteri Unicode).
Va notato che, a differenza di quanto si possa dedurre leggendo ``Programming Perl''
[Programmare Perl, NdT] (il libro del Cammello) o altro, :raw
non è
semplicemente l'inverso di :crlf
, anche gli altri strati che potrebbero influire
sulla natura binaria del file vengono disabilitati. Consultate the PerlIO manpage, the perlrun manpage
e la discussione sulla variabile d'ambiente PERLIO.
Le direttive :bytes
, :crlf
, :utf8
e qualsiasi altra direttiva nella forma
:...
, sono chiamate strati di I/O. Per stabilire gli strati di I/O predefiniti,
è possibile utilizzare la direttiva open
. Si veda the open manpage.
Il parametro STRATO di binmode() è descritto come ``DISCIPLINE'' [``DISCIPLINA'', NdT] su ``Programming Perl, 3rd Edition''. In ogni caso, dal momento della pubblicazione di questo libro, da molti conosciuti come il ``Camel III'', il consenso per quanto riguarda il nome di questa funzionalità si è spostato da ``disciplina'' a ``strato''. Tutta la documentazione di questa versione di Perl si riferisce dunque a ``strato'' anziché a ``disciplina''. Ora torniamo alla documentazione regolare...
Per marcare FILEHANDLE come UTF-8, usate :utf8
.
In generale, binmode()
dovrebbe essere chiamato dopo open()
ma prima che qualsiasi
altra operazione di I/O sia compiuta sul filehandle. Chiamare binmode()
causa che
tutte le operazioni di output (e forse di input) non concluse sul filehandle vengano
completate. Un'eccezione a ciò è rappresentata dallo strato
:encoding
, che cambia la condifica predefinita di caratteri per l'handle, consultate
the open manpage. A volte è necessario impostare lo strato :encoding
nel mezzo delle
operazioni sul filehandle ed esso non causa il completamento delle operazioni di I/O in
corso. Inoltre :encoding
implicitamente spinge lo strato :utf8
in cima a se stesso,
dato che internamente il Perl opererà su caratteri Unicode codificati con UTF-8.
Il sistema operativo, i driver dei device, le librerie C, ed il sistema Perl a tempo di
esecuzione, lavorano tutti assieme per permettere al programmatore di utilizzare un
singolo carattere (\n
) come terminatore di linea, indipendentemente dalla
rappresentazione esterna. Su molti sistemi operativi, la rappresentazione nativa dei file
di testo equivale a quella esterna, ma su alcuni sistemi la rappresentazione esterna di
\n
è composta da più di un carattere.
Mac OS, tutte le varianti di Unix, ed i file Stream_LF su VMS utilizzano un singolo
carattere per terminare ciascuna riga nella rappresentazione esterna del testo (anche se
quel singolo carattere è un CARRIAGE RETURN su Mac OS ed un LINE FEED su Unix e
sulla maggior parte dei file VMS). In altri sistemi quali OS/2, DOS e le varie versioni
di MS-Windows, il vostro programma vede \n
come un semplice \cJ
, ma ciò che
in realtà viene memorizzato nei file di testo è una coppia di caratteri
\cM\cJ
. Ciò singnifica che, se non usate binmode()
su tali sistemi, le
sequenze che su disco sono \cM\cJ
verranno convertite in \n
al momento dell'input,
ed ogni eventuali \n
nel vostro programma verrà convertito in \cM\cJ
al
momento dell'output. Questo è ciò che desiderate per i file di testo,
ma può rivelarsi disastroso per i file binari.
Un'altra conseguenza dell'utilizzo di binmode()
è (su alcuni sistemi)
rappresentata dal fatto che gli speciali delimitatori che indicano la fine del file
verranno visti come parte del flusso di dati. Per i sistemi operativi della famiglia
Microsoft, ciò significa che se i vostri dati binari contengono \cZ
, il
sottosistema di I/O considererà tale carattere come la fine del file, a meno che
non usiate binmode().
binmode()
non è importante solamente per le operazioni readline()
e print(), ma
anche quando si utilizzano read(), seek(), sysread(), syswrite()
e tell()
(consultate
the perlport manpage per ulteriori dettagli). Date un'occhiata alle variabili $/
e $\
in
the perlvar manpage per capire come fare ad impostare manualmente le vostre sequenze di
terminatori di linea per l'input e l'output.
bless
[letteralmente benedizione, consacrazione, NdT] è spesso l'ultima
cosa in un costruttore, restituisce per convenienza il riferimento. Usate sempre la versione
a due argomenti se una classe derivata potrebbe ereditare la funzione che effettua il bless.
Consultate the perltoot manpage e the perlobj manpage per maggiori dettagli sull'operazione di bless
(e i blessing) degli oggetti.
Prendete sempre in considerazione il fatto di effettuare il bless di oggetti nelle NOMECLASSE che utilizzano sia maiuscole che minuscole. I namespace con tutte le lettere minuscole sono considerati riservati per le direttive del Perl. I tipi interni hanno tutti i nomi maiuscoli. Per prevenire la confusione, potete pure evitare tali nomi di package. Assicuratevi che NOMECLASSE sia un valore vero.
Consultate Perl Modules in the perlmod manpage [``Moduli Perl'', NdT].
eval
o require
, altrimenti
il valore indefinito. In un contesto di lista, restituisce
($package, $nomefile, $linea) = caller;
Con ESPR, restituisce dell'informazione addizionale che il debugger utilizza per stampare una traccia dello stack. Il valor di ESPR indica quanti record di attivazione risalire prima di quello corrente.
($package, $nomefile, $linea, $subroutine, $ha_argomenti, $voglio_array, $testo_eval, $e_richiesto, $indicazioni, $maschera_di_bit) = caller($i);
Qui, a $subroutine può essere applicato (eval)
se il record non è una
subroutine ma un eval
. In questo caso, vengono impostati elementi addizionali quali
$testo_eval e $e_richiesto
: $e_richiesto
è vero se il record è
creato da un'istruzione require
o use
, $testo_eval contiene il testo
dell'istruzione eval ESPR
. In particolare, per un'istruzione eval BLOCCO
, a
$filename è applicato (eval)
, ma $testo_eval è indefinito.
(Va notato anche che ogni istruzione use
crea un record require
all'interno di un
record eval ESPR
. A $subroutine può anche essere applicato (sconosciuto)
se a questa particolare subroutine capita di essere cancellata dalla tabella dei simboli.
$ha_argomenti
è vero se viene impostata una nuova istanza di @_
per il
record. $indicazioni
e $maschera_di_bit
contengono indicazioni prammatiche che sono
state utilizzate per compilare il chiamante. I valori $indicazioni
e
$maschera_di_bit
sono soggetti a cambiamenti fra le versioni del Perl e non sono
intese per l'uso esterno.
Inoltre, quando viene chiamato all'interno del package DB, il chiamante restituisce
informazioni più dettagliate: esso imposta la variabile di lista @DB::args
per essere gli argomenti con i quali la subroutine è stata invocata.
Siate consapevoli che l'ottimizzatore potrebbe avere ottimizzato a parte i record di
attivazione, prima che il chiamante
abbia una possibilità di ottenere
l'informazione. Questo significa che chiamante(N)
potrebbe non restituire
l'informazione che riguarda il record di attivazione che vi aspettate di ottenere per
N > 1
. In particolare, @DB::args
potrebbe avere l'informazione dalla volta
precedente che caller
è stato chiamato.
$ENV{HOME}
, se
impostata; altrimenti, cambia la directory corrente in quella specificata in
$ENV{LOGDIR}
. (Sotto VMS, viene controllata anche la variabile $ENV{SYS$LOGIN}
).
Se nessuna di queste variabili è impostata, chdir
non ha alcun effetto.
Restituisce vero in caso di successo, falso negli altri casi. Consultate l'esempio in
die
.
Su sistemi che supportano fchdir, potreste passare come argomenti un file handle oppure un directory handle. Su sistemi che non supportano fchdir, passare gli handle produce un errore fatale a tempo di esecuzione.
0644
va bene, '0644'
no.
Restituisce il numero di file modificati con successo. Consultate anche oct, se tutto
ciò che avete a disposizione è una stringa.
$cnt = chmod 0755, 'pippo', 'pluto'; chmod 0755, @eseguibili; $modalita = '0644'; chmod $modalita, 'pippo'; # !!! imposta la modalita` a # --w----r-T $modalita = '0644'; chmod oct($modalita), 'pippo'; # questo e` meglio $modalita = 0644; chmod $modalita, 'pippo'; # questo e` il migliore
Su sistemi che supportano fchmod, potreste passare i file handle tra i file. Su sistemi che non supportano fchmod, passare file handle produce un errore fatale a tempo di esecuzione.
open(my $fh, "<", "pippo"); my $perm = (stat $fh)[2] & 07777; chmod($perm | 0600, $fh);
Potete anche importare le costanti simboliche S_I*
dal modulo Fcntl:
use Fcntl ':mode';
chmod S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, @eseguibili; # Questo e` identico al chmod 0755 dell'esempio sopra.
$/
(conosciuta anche come $INPUT_RECORD_SEPARATOR [record separatore di input, NdT]
nel modulo English
). La funzione restituisce il numero totale di caratteri rimossi da
tutti i suoi argomenti. È spesso utilizzato per rimuovere il newline dalla fine di un
record in input, quando temete che il record possa essere sprovvisto del suo newline. Quando
è utilizzata in paragraph mode [modalità paragrafo, NdT] ($/ = ""
), rimuove
tutti i newline in coda ad una stringa. Quando è utilizzata in slurp mode
[modalità slurp, NdT] ($/ = undef
) o con una lunghezza di record fissa ($/
è un riferimento ad un intero o a qualcosa di simile, consultate the perlvar manpage), chomp()
non rimuoverà nulla. Se VARIABILE viene omessa, chomp agisce su $_
. Ad esempio:
while (<>) { chomp; # rimuove \n dall'ultimo campo @array = split(/:/); # ... }
Se VARIABILE è un hash, chomp()
agisce sui valori dell'hash, ma non sulle sue chiavi.
Potete utilizzare chomp su qualsiasi cosa che sia un lvalue [valore a sinistra di un'espressione, NdT], incluso un assegnamento:
chomp($cwd = `pwd`); chomp($risposta = <STDIN>);
Se usate chomp()
su una lista, viene effettuato il chomp di ogni elemento, e viene restituito il
numero totale di caratteri rimossi.
Se la direttiva encoding
è nello scope, allora
le lunghezze che vengono restituite sono calcolate a partire dalla lunghezza di $/
in
caratteri Unicode che non è sempre la stessa cosa della lunghezza di $/
nella
codifica nativa.
Va notato che le parentesi sono necessarie quando usate chomp()
su qualsiasi cosa che non sia una
variabile semplice. Ciò deriva dal fatto che chomp $cwd = `pwd`;
è
interpretato come (chomp $cwd) = `pwd`;
, anziché come chomp( $cwd = `pwd` )
, come
vi potreste aspettare. Similmente, chomp $a, $b
è interpreato come chomp($a), $b
anziché come chomp($a, $b)
.
s/.$//s
perché
non scandisce né copia la stringa. Se VARIABILE viene omessa,
taglia $_
. Se VARIABILE è un hash, taglia i valori
dell'hash, ma non le sue chiavi.
Potete utilizzare chop su qualsiasi cosa che sia un lvalue [valore a sinistra di un'espressione, NdT], incluso un assegnamento.
Chiamando chop su una lista, ogni elemento viene tagliato. Viene
restituito solo il valore dell'ultimo chop
effettuato.
Va notato che chop
restituisce l'ultimo carattere. Per ottenere tutto
tranne l'ultimo carattere, utilizzate substr($stringa, 0, -1)
.
Si veda anche chomp.
$cnt = chown $uid, $gid, 'pippo', 'pluto'; chown $uid, $gid, @nomifile;
Su sistemi che supportano fchown, potreste passare i file handle tra i file. Su sistemi che non supportano fchmod, passare file handle produce un errore fatale a tempo di esecuzione.
Di seguito è riportato un esempio che risolve le uid non numeriche servendosi del file passwd:
print "Utente: "; chomp($utente = <STDIN>); print "File: "; chomp($pattern = <STDIN>);
($login,$pass,$uid,$gid) = getpwnam($utente) or die "$utente non e` presente nel file passwd";
@ary = glob($pattern); # espande i nomi dei file chown $uid, $gid, @ary;
Sulla maggior parte dei sistemi, non è consentito cambiare il proprietario dei file a meno che non si sia superuser. Dovreste tuttavia essere in grado di cambiare il gruppo impostandolo ad uno qualsiasi dei vostri gruppi secondari. Su sistemi non sicuri, queste restrizioni potrebbero essere meno rigide, ma assumere una cosa del genere non è portabile. Sui sistemi POSIX, potete verificare questa condizione in questo modo:
use POSIX qw(sysconf _PC_CHOWN_RESTRICTED); $chown_possibile = not sysconf(_PC_CHOWN_RESTRICTED);
chr(65)
è "A"
sia in ASCII che in Unicode, e chr(0x263a)
è una faccina sorridente in
Unicode. Va notato che i caratteri da 127 a 255 (inclusi) di default non sono codificati in
Unicode per ragioni di compatibilità all'indietro (ma consultate the encoding manpage).
Se NUMERO viene omesso, utilizza $_
.
Per l'inverso di questa funzione, utilizzate ord.
Va notato che mediante la direttiva bytes
, il NUMERO viene mascherato dagli otto bit bassi.
Consultate the perlunicode manpage e the encoding manpage per maggiori informazioni su Unicode.
/
, per il vostro
processo e tutti i suoi figli (Non cambia la vostra directory corrente, che non viene modificata).
Per motivi di sicurezza, questa chiamata è riservata al superuser. Se NOMEFILE viene
omesso, esegue un chroot
su $_
.
Non è necessario che voi chiudiate il FILEHANDLE se immediatamente andrete a fare
un'altra open
sul filehandle perché open
lo chiuderà per voi.
(Si veda open
). Ad ogni modo, un'esplicita close
su di un file di input riazzererà
il contatore di linea ($.
), mentre non lo farà la close implicita fatta da open
.
Se il filehandle proviene da una open su pipe, close
restituirà in aggiunta falso se
fallisce una delle altre chiamate di sistema coinvolte, oppure se il programma esce con uno stato
non-zero. (Se il solo problema è che il programma sia uscito come non-zero, $!
verrà impostato a 0
). Anche chiudere una pipe fa attendere che il processo in
esecuzione su quella pipe sia completato, nel caso vogliate esaminare successivamente l'output
della pipe, e implicitamente pone in $?
il valore di stato dell'uscita di quel comando.
Chiudere prematuramente la lettura finale di una pipe (cioè prima che il processo che sta scrivendo su di essa dall'altra estremità l'abbia chiusa) si risolverà in una SIGPIPE che verrà recapitata a chi sta scrivendo. Se l'altra estremità non può occuparsene, ci si assicuri di leggere tutti i dati prima di chiudere la pipe.
Esempio:
open(OUTPUT, '|sort >pippo') # pipe da ordinare or die "Non posso avviare sort: $!"; #... # stampo qualcosa in output close OUTPUT # aspetto che il sort termini or warn $! ? "Errore nel chiudere la sort del pipe: $!" : "Stato di uscita $? dal sort"; open(INPUT, 'pippo') # ricevo i risultati di sort or die "Non posso aprire 'pippo' per l'input: $!";
FILEHANDLE può essere un'espressione i cui valori possono essere usati come un filehandle indiretto, solitamente il nome effettivo del filehanlde.
opendir
e restituisce l'esito di
quella chiamata di sistema.
continue
in realtà è un'istruzione per il controllo di flusso
piuttosto che una funzione. Se c'è un continue
BLOCCO associato
ad un BLOCCO (generalmente in un while
o in un foreach
), questo
viene eseguito appena prima che la condizione venga valutata nuovamente,
come la terza parte di un ciclo for
in C. Può quindi essere
utilizzato per incrementare un contatore, anche se il ciclo viene
proseguito con l'istruzione next
(che è simile alla funzione
continue
del C).
last
, next
o redo
possono apparire in un blocco continue
.
last
e redo
si comporteranno come se fossero stati eseguiti dal
blocco principale. Così farà anche next
, ma
poiché questo eseguirà a sua volta un blocco continue
,
i risultati potrebbero essere molto divertenti.
while (ESPR) { ### redo porta sempre qui fai_qualcosa; } continue { ### next porta sempre qui fai_qualcos_altro; # e di nuovo all'inizio del ciclo per valutare ESPR } ### last porta sempre qui
Omettere la sezione continue
è semanticamente equivalente
ad utilizzarne una vuota, logico quanto basta. In questo caso, next
porta direttamente alla valutazione della condizione all'inizio del ciclo.
$_
.
Per l'operazione del coseno inverso, potete utilizzare la funzione
Math::Trig::acos()
, oppure questa relazione:
sub acos { atan2( sqrt(1 - $_[0] * $_[0]), $_[0] ) }
crypt(3)
nella libreria C (assumendo che ce ne abbiate davvero una, che
non sia stata estirpata quale potenziale armamento).
crypt()
è una funzione non invertibile. TESTOINCHIARO e SEME sono
convertiti in una breve stringa, chiamata digest, che viene restituita.
I medesimi TESTOINCHIARO e SEME restituiranno sempre la stessa stringa,
ma non c'è nessun modo (conosciuto) per ottenere il TESTOINCHIARO
dall'hash. Piccoli cambiamenti nel TESTOINCHIARO o nel SEME ha come
risultato dei grandi cambiamenti nel digest.
Non c'è una funzione di decifratura. Questa funzione non è
per nulla utile alla crittografia (per questa cosa, date un'occhiata ai moduli
Crypt sul vostro mirror CPAN più vicino) e il nome ``crypt'' [cripta, NdT]
è un po' un termine improprio. Il suo uso principale È invece
quello di controllare se due parti di testo sono le stessem senza dover
trasmettere o immagazzinare il testo stesso. Un esempio è controllare
se viene fornita una password corretta. È il digest della password ad
essere immagazzinato e non la password stessa. L'utente digita una password
che viene sottoposta a crypt()
con il medesimo digest memorizzato quale seme.
Se i due digest corrispondono, la password è corretta.
Quando effetuate la verifica di una stringa digest esistente, dovreste usare il
digest come seme (come crypt($chiaro, $digest) eq $digest
). La parte
SEME usata per creare il digest è visibile come parte del digest.
Questo assicura che crypt()
calcolerà l'hash della nuova stringa
con lo stesso seme del digest. Questo fa sì che il vostro codice funzioni
sia con la crypt standard che con implementazioni più esotiche.
In altre parole, non presumete nulla sulla stringa restituita, o su
quanti byte siano siano significativi nel digest.
Tradizionalmente, il risultato è una stringa di 13 byte: i
primi due sono il seme, e sono seguiti da 11 byte appartenenti
all'insieme [./0-9A-Za-z]
, e solo i primi otto byte della stringa
digest sono significativi; tuttavia, schemi di hashing alternativi
(come MD5), schemi di sicurezza di livello più elevato
(come C2) ed implementazioni su piattaforme non-UNIX, possono
generare stringhe diverse.
Quando scegliete un nuovo seme, create una stringa casuale di due
caratteri, i quali devono appartenere all'insieme [./0-9A-Za-z]
(come join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]
).
Questo insieme di caratteri è solo una raccomandazione; i
caratteri permessi nel seme dipendono esclusivamente dalla vostra
libreria crypt di sistema, e il Perl non può limitare i semi
accettati da crypt()
.
Ecco un esempio che ci assicura che chiunque faccia girare questo programma conosca la propria password:
$pwd = (getpwuid($<))[1];
system "stty -echo"; print "Password: "; chomp($parola = <STDIN>); print "\n"; system "stty echo";
if (crypt($parola, $pwd) ne $pwd) { die "Spiacente...\n"; } else { print "ok\n"; }
Chiaramente, scrivere la vostra password a chiunque ve la richieda non è saggio.
La funzione crypt non è adatta per calcolare il valore di hash per grandi quantità di dati, non del tutto almeno, perché non potete ottenere le vostre informazioni di nuovo in chiaro. Date un'occhiata al modulo the Digest manpage per ulteriori robusti algoritmi.
Se usate crypt()
su una stringa Unicode (che potenzialmente
contiene caratteri con codice superiore a 255), Perl cerca di dare
un senso alla situazione cercando di riportare (una copia de) la
stringa ad una stringa a otto bit prima di chiamare crypt()
(su
quella copia). Se ciò funziona, bene. Altrimenti, crypt()
termina con Wide character in crypt
[crypt su carattere esteso, NdT]
untie
].
Rompe il legame tra un file DBM ed un hash.
tie
].
Questa funzione effettua un legame tra un file di tipo dbm(3),
ndbm(3), sdbm(3), gdbm(3)
oppure Berkeley DB in un hash. HASH
è il nome dell'hash. (Diversamente dalla normale open
,
il primo argomento non è un filehandle, anche se ci
assomiglia). NOMEDB è il nome del database (senza
l'estensione .dir o .pag, se presente). Se il database non
esiste, viene creato con una protezione specificata da MASCHERA
(come modificato dalla funzione umask
). Se il vostro sistema
supporta solo le vecchie funzioni DBM, nel vostro programma
potete effettuare solo una dbmopen
. In vecchie versioni di
Perl, se il vostro sistema non possedeva né DBM né
ndbm, chiamare dbmopen
produceva un errore bloccante; ora
ciò ricade su sdbm(3).
Se non avete accesso in scrittura sul file DBM, potete solo
leggere i valori dell'hash e non impostarli. Se volete testare la
possibilità di scrivere, usate o i test sui file oppure
tentate di impostare l'elemento di un hash fittizio all'interno di
un eval
che catturerà l'errore.
Va notato che le funzioni come keys
e values
possono
restituire liste enormi quando sono usate su grandi file DBM.
Potreste preferire l'uso della funzione each
per iterare su
grandi file DBM. Un esempio:
# stampa gli scostamenti del file history dbmopen(%HIST,'/usr/lib/news/history',0666); while (($chiave,$val) = each %HIST) { print $chiave, ' = ', unpack('L',$val), "\n"; } dbmclose(%HIST);
Consultate anche the AnyDBM_File manpage per una descrizione più generale sui pro e contro dei vari approcci dbm, come pure the DB_File manpage per una implementazione particolarmente ricca.
Potete controllare che libreria DBM state usando tramite il caricamento della libreria prima di richiamare dbmopen():
use DB_File; dbmopen(%NS_Hist, "$ENV{HOME}/.netscape/history.db") or die "Non e` possibile aprire il file history di netscape: $!";
undef
. Se ESPR non è
presente, il controllo viene fatto su $_
.
Molte operazioni restituiscono undef
per indicare l'insuccesso,
la fine del file, un errore di sistema, una variabile non
inizializzata, ed altre condizioni eccezionali. (Un semplice test
Booleano non è in grado di distinguere tra undef
, zero,
la stringa vuota, e "0"
, che sono tutti ugualmente falsi). Va
notato che, poiché undef
è uno scalare valido,
la sua presenza non indica necessariamente una condizione
eccezionale: pop
restituisce undef
guardo il suo argomento
è un array vuoto, oppure quando l'elemento da restituire
è esso stesso undef
.
Potete anche usare defined(&pippo)
per controllare se una
subroutine &pippo
è stata definita in precedenza. Il
valore restituito non è variato da eventuali future
dichiarazioni di &pippo
. Va notato che un subroutine non
definita può ancora essere chiamabile: il suo package
può avere un metodo AUTOLOAD
che ne provoca l'esistenza
la prima volta che viene chiamata, consultate the perlsub manpage.
L'uso di defined
su strutture (hash ed array) è deprecato.
Indicava quanta memoria era stata allocata per una determinata
struttura. Questa caratteristica potrebbe scomparire nelle future
versione di Perl. Al suo posto, fareste meglio ad usare un semplice
test di dimensione:
if (@un_array) { print "l'array contiene elementi\n" } if (%un_hash) { print "l'hash contiene membri\n" }
Quando utilizzato su un elemento di un hash, defined
vi dice se
quel valore è definito o meno, non se esiste o meno la
chiave nell'hash. Usate exists se vi interessa la seconda
informazione.
Esempi:
print if defined $switch{'D'}; print "$val\n" while defined($val = pop(@ary)); die "Non posso leggere il link $sym: $!" unless defined($valore = readlink $sym); sub pippo { defined &pluto ? &$pluto(@_) : die "Non esiste pluto"; } $debugging = 0 unless defined $debugging;
Nota: Molta gente tende ad abusare di defined
, e poi si
sorprende di scoprire che il numero 0
e ""
(la stringa di
lunghezza zero) sono, in realtà, valori definiti. Per
esempio, se scrivete:
"ab" =~ /a(.*)b/;
La ricerca del pattern ha successo, e $1
risulta definito,
nonostante esso abbia trovato ``nulla''. Non è che non ha
veramente trovato nulla. Piuttosto, ha trovato qualcosa che era
lungo zero caratteri. Tutto ciò è piuttosto chiaro
e corretto. Quando una funzione restituisce un valore indefinito,
ammette di non essere in grado di fornire una risposta corretta.
Quindi dovreste usare defined
solo quando dubitate
dell'integrità di ciò che state tentando di fare.
Nelle altre circostanze, una semplice comparazione on 0
o ""
è ciò che desiderate.
exists()
è vera (oppure fino
a 0, se tale elemento non esiste).
Restituisce una lista con lo stesso numero di elementi che si è tentato di eliminare. Ogni elemento di questa lista consiste o nel valore dell'elemento eliminato, oppure nel valore undef. In contesto scalare, questo vuol dire che il valore restituito è il valore dell'ultimo elemento eliminato (o il valore indefinito se quell'elemento non esisteva).
%hash = (pippo => 11, pluto => 22, paperino => 33); $scalare = delete $hash{pippo}; # $scalare e` 11 $scalare = delete @hash{qw(pippo pluto)}; # $scalare e` 22 @array = delete @hash{qw(pippo pluto paperino)}; # @array e` (undef,undef,33)
Cancellare da %ENV
modifica l'ambiente. Cancellare da un
hash legato ad un file DBM cancella le voci dal file DBM.
Cancellare da un hash o array legato potrebbe non necessariamente
restituire qualcosa.
Cancellare effettivamente un elemento da un array riporta
quella posizione dell'array al suo stato iniziale, non
inizializzato. Successive verifiche con exists()
dello stesso elemento restituiranno falso. Inoltre,
cancellare elementi nel mezzo di un array
non farà scorrere in basso l'indice degli
elementi successivi. Usate splice()
per questo.
Si veda exists.
Il seguente codice cancella (in maniera inefficiente) tutti i valori di %HASH e di @ARRAY:
foreach $chiave (keys %HASH) { delete $HASH{$chiave}; }
foreach $indice (0 .. $#ARRAY) { delete $ARRAY[$indice]; }
Questi fanno la stessa cosa:
delete @HASH{keys %HASH};
delete @ARRAY[0 .. $#ARRAY];
Ma entrambi risultano più lenti che l'assegnare semplicemente la lista vuota oppure rendere indefiniti %HASH o @ARRAY:
%HASH = (); # svuota completamente %HASH undef %HASH; # dimentica che %HASH sia # mai esistito
@ARRAY = (); # svuota completamente @ARRAY undef @ARRAY; # dimentica che %ARRAY sia # mai esistito
Va notato che ESPR può essere arbitrariamente complessa, purché l'operazione finale denoti l'elemento di un hash, di un array, una porzione di un hash o di un array:
delete $ref->[$x][$y]{$chiave}; delete @{$ref->[$x][$y]}{$chiave1, $chiave2, @altrechiavi};
delete $ref->[$x][$y][$indice]; delete @{$ref->[$x][$y]}[$indice1, $indice2, @altriindici];
eval
, stampa il valore di LISTA su STDERR
ed esce
dal programma con il valore corrente di $!
(errno). Se $!
è 0
, il codice di uscita è il valore di
($? >> 8)
(stato del `comando` in backtick). Se
($? >> 8)
è 0
, esce con codice 255
. All'interno
di un eval()
, il messaggio di errore viene memorizzato in $@
e
il blocco eval
viene terminato con undef
come valore restituito.
Questo rende die
il modo di implementare una eccezione.
Esempi equivalenti:
die "Impossibile cambiare directory in spool: $!\n" unless chdir '/usr/spool/news'; chdir '/usr/spool/news' or die "Impossibile cambiare directory in spool: $!\n"
Se l'ultimo elemento di LISTA non termina con un ritorno a capo, la
riga corrente dello script e la riga corrente dell'input (ove esistente)
vengono stampate con un ritorno a capo in fondo. Va notato che la
``riga corrente dell'input'' (chiamata anche ``chunk'') è soggetto alla
nozione di ``linea'' correntemente utilizzata, ed è disponibile anche
nella variabile $.
. Consultate $/ in the perlvar manpage e $. in the perlvar manpage.
Suggerimento: a volte, aggiungere ", stopped"
[interrotto, NdT] al vostro
messaggio può avere senso quando viene aggiunta la stringa
"at pippo line 123"
. Supponiamo che stiate facendo girare lo script
``canasta''.
die "/etc/games non va bene"; die "/etc/games non va bene, interrotto";
producono, rispettivamente
/etc/games non va bene at canasta line 123. /etc/games non va bene, interrotto at canasta line 123.
Si veda anche exit(), warn(), e il modulo Carp.
Se LISTA è vuota e $@
già contiene un valore
(generalmente da un eval precedente), questo valore viene riutilizzato
con l'aggiunta di un "\t...propagated"
[propagato, NdT]. Può
essere utile per propagare delle eccezioni:
eval { ... }; die unless $@ =~ /Expected exception/;
Se LISTA è vuota e $@
contiene un oggetto che ha un metodo
PROPAGATE
, questo metodo sarà chiamato con il nome del file
e il numero di riga come parametri aggiuntivi. In questo caso, il
valore restituito rimpiazza il valore in $@
, ossia come se fosse
stato chiamato <$@ = eval { $@-
PROPAGATE(__FILE__, __LINE__) }; >>.
Se $@
è vuoto, viene utilizzata la stringa "Died"
[terminato, NdT].
die()
può anche essere chiamato con un argomento che sia un
riferimento. Se questo accade all'interno di un eval(), $@ contiene
quell'oggetto. Questo comportamento permette di implementare delle
eccezioni più sofisticate, utilizzando degli oggetti che
possono contenere dati relativi alla natura dell'eccezione. Questo
schema è a volte preferibile all'utilizzo di espressioni
regolari per verificare la presenza di particolari valori nella
stringa $@. Ecco un esempio:
use Scalar::Util 'blessed';
eval { ... ; die Unqualche::Modulo::Eccezione->new( PIPPO => "pluto" ) }; if ($@) { if (blessed($@) && $@->isa("Unqualche::Modulo::Eccezione")) { # gestisce Unqualche::Modulo::Eccezione } else { # gestisce tutte le altre possibili eccezioni } }
Poiché perl converte in stringa i messaggi non gestiti prima di visualizzarli, potreste implementare un overload dell'operatore di conversione a stringa su tali oggetti eccezione. Consultate the overload manpage per maggiori dettagli.
Potete fare in modo che venga chiamata una funzione appena prima che
die
faccia il suo dovere, impostando un riferimento in $SIG{__DIE__}
.
La funzione indicata sarà chiamata con il testo dell'errore e
può, volendo, modificare il messaggio d'errore chiamando
nuovamente die
. Si veda $SIG{expr} in the perlvar manpage per dettagli sull'utilizzo di
%SIG
, e eval BLOCK per qualche esempio. Nonostante questa funzionalità
dovesse essere eseguita solo immediatamente prima dell'uscita dal programma,
ma non è più così -- la funzione
in $SIG{__DIE__}
viene chiamata anche all'interno di blocchi o
stringhe in eval()! Se si vuole che la funzione non faccia nulla in questi
casi, mettere un
die @_ if $^S;
come prima linea della funzione (si veda $^S in the perlvar manpage). Poiché questo può causare effetti collaterali non desiderati, questo comportamento non intuitivo potrebbe essere modificato in una versione successiva.
while
o until
, esegue il BLOCCO
una volta prima di testare la condizione del ciclo (Su altre istruzioni, i
modificatori di loop testano prima il condizionale).
do BLOCCO
non conta come un ciclo, dunque le istruzioni di
controllo del ciclo next
, last
o redo
non possono essere usati
per lasciare o ricominciare il blocco. Consultate the perlsyn manpage per strategie
alternative.
SUBROUTINE(LISTA)
do 'stat.pl';
è proprio come
eval `cat stat.pl`;
eccetto che è più efficiente e concisa, tiene traccia del
nome file corrente per i messaggi d'errore, ricerca directory di @INC e
aggiorna %INC
se il file viene trovato. Consultate
Predefined Names in the perlvar manpage [Nomi predefiniti, NdT] per queste varabili.
Differisce anche per il fatto che il codice valutato con do NOMEFILE
non può vedere i lessicali nello scope che lo include;
eval STRINGA
li vede. È lo stesso, comunque, nel fatto che esso
riesegue un'analisi sintattica del file ogni qualvolta viene chiamato,
dunque probabilmente non volete fare questo all'interno di un ciclo.
Se do
non può leggere il file, esso restituisce undef e imposta
$!
con l'errore. Se do
può leggere il file ma non lo può
compilare, restituisce undef e imposta un messaggio di errore in $@
. Se il
file è compilato con successo, do
restituisce il valore dell'ultima
espressione valutata.
Va notato che l'inclusione di moduli di libreria viene fatta meglio con gli
operatori use
e require
che eseguono anche un controllo automatico
degli errori e sollevano un'eccezione se ci fosse un problema.
Potreste gradire l'utilizzo di do
per leggere in un file di configurazione
di un proramma. Il controllo manuale degli errori può essere fatto in
questo modo:
# legge nei file di configurazione: prima in quelli di sistema poi in quelli utente for $file ("/share/prog/default.rc", "$ENV{HOME}/.unqualcheprogrammarc") { unless ($valore_restituito = do $file) { warn "non si e` potuto fare l'analisi sintattica di $file: $@" if $@; warn "non si e` potuto eseguire do sul $file: $!" unless defined $valore_restituito; warn "non si e` potuto eseguire il $file" unless $valore_restituito; } }
goto ETICHETTA
(con tutte le restrizioni di cui soffre goto
).
Pensate ad esso come ad un goto con un core dump nel mezzo, e poi una
reincarnazione. Se ETICHETTA
viene omesso, ricomincia il programma da
capo.
ATTENZIONE: Ogni file aperto al momento del dump non sarà più aperto quando il programma si reincarnerà, con una possibile confusione di risultati dal lato del Perl.
Questa funzione è ora ampiamente obsoleta, in parte a causa
dell'estrema difficoltà nel convertire un file di core in un
eseguibile e perché è stato superato dai veri compilatori
di backend che generano bytecode portabile e codice C compilabile. Questo
è il motivo per cui ora lo dovreste invocare come CORE::dump()
,
se non volete essere avvisati di un possibile errore di battitura.
Se state considerando l'utilizzo di dump per rendere i vostri programmi
più veloci, prendete in considerazione la generazione di bytecode o
di codice C nativo come descritto in perlcc. Se state solamente tentando
di accelerare uno script CGI, prendete in considerazione l'utilizzo di
mod_perl
, estensione di Apache, oppure il modulo CPAN CGI::Fast.
Potreste prendere in considerazione anche l'autoloading o il selfloading,
che almeno fanno sembrare più veloce il vostro programma.
Gli elementi vengono restituiti in un ordine
apparentemente casuale. L'effettivo ordine casuale
è soggetto a cambiamenti nelle future versioni
di Perl, ma è garantito essere lo stesso ordine
che la funzione keys
o values
produrrebbero dallo
stesso hash (non modificato). A partire dalla versione 5.8.1 di Perl,
per questioni di sicurezza l'ordinamento è differente anche tra
differenti esecuzioni di Perl (si consulti Algorithmic Complexity Attacks in the perlsec manpage
[``Attacchi di Complessità Algoritmica'', NdT]).
Quando l'hash è stato letto interamente,
in contesto di lista viene restituito un array null
(che quando viene assegnato produce un valore falso 0
),
e undef
in contesto scalare. La prossima chiamata a
each
dopo questa comincerà l'iterazione
un'altra volta. Esiste un singolo iteratore per ogni
hash, condiviso da tutte le chiamate a each
, keys
e values
nel programma; può essere
azzerato leggendo tutti gli elementi dall'hash, oppure
valutando keys HASH
o values HASH
. Se aggiungete
o cancellate elementi a un hash mentre state iterando
su di esso, potreste avere degli elementi saltati
o ripetuti, quindi non fatelo. Eccezione: è sempre
sicuro cancellare l'elemento restituito più
di recente da each()
, il che significa che il
seguente codice funzionerà:
while (($key, $value) = each %hash) { print $key, "\n"; delete $hash{$key}; # E<egrave> sicuro }
Il seguente codice stampa l'ambiente come il programma printenv(1), con l'unica differenza che lo fa in un'ordine differente:
while (($key,$value) = each %ENV) { print "$key=$value\n"; }
ungetc
su di esso, dunque ciò non è
molto utile in un contesto interattivo). Non leggete da un file di
terminale (oppure non chiamate eof(FILEHANDLE)
su di esso) dopo che
si è raggiunta la fine-del-file. Se lo fate, i tipi di file
quali i terminali potrebbero perdere la condizione di file-del-file.
Un eof
senza un argomento utilizza l'ultimo file letto. L'uso di
eof()
con parentesi vuote, è molto differente. Si riferisce
allo pseudo file formato dai file elencati sulla linea di comando e
acceduti attraverso l'operatore <>
. Poiché <>
non
è esplicitamente aperto come lo è un normale filehandle,
un eof()
prima che venga usato un <>
farà sì
che venga esaminato @ARGV
per determinare se sia disponibile l'input.
In maniera analoga, un eof()
dopo che <>
abbia restituito
fine-del-file, presupporrà che stiate elaborando un'altra lista
di @ARGV
, e se non avete impostato @ARGV
, esso leggerà
l'input da STDIN
; consultate I/O Operators in the perlop manpage
[``Operatori di I/O'', NdT].
In un ciclo while (<>)
, eof
o eof(ARGV)
possono essere
usati per determinare la fine di ogni file, eof()
determinerà solo la file dell'ultimo file. Esempi:
# ripristina la numerazione di linea su ogni file di input while (<>) { next if /^\s*#/; # tralascia i commenti print "$.\t$_"; } continue { close ARGV if eof; # Non eof()! }
# inserisce delle lineette appena prima dell'ultima linea dell'ultimo file while (<>) { if (eof()) { # controlla la fine dell'utimo file print "--------------\n"; } print; last if eof(); # necessario se stiamo leggendo da terminale }
Suggerimento pratico: in Perl non si ha quasi mai la necessità
di usare eof
visto che gli operatori di input restituiscono tipicamente
undef
quando esauriscono i dati o se c'è stato un errore.
eval
effettua un'esecuzione. Se ESPR
viene omessa, esso valuta $_
. Questa forma viene usata tipicamente
per ritardare la verifica sintattica e la successiva esecuzione del
testo di ESPR fino al tempo di esecuzione.
Nella seconda forma, il codice all'interno del BLOCCO viene verificato
sintatticamente solo una volta, allo stesso momento in cui il codice che
circonda lo stesso eval
viene verificato sintatticamente, ed eseguito
all'interno del contesto del programma Perl corrente. Questa forma viene
usata tipicamente per catturare le eccezioni in maniera più
efficiente che non la prima (vedete qui sotto), pur fornendo anche il
vantaggio di controllare il codice dentro BLOCCO a tempo di compilazione.
Il punto e virgola finale, se presente, potrebbe essere omesso dal valore di ESPR o all'interno del BLOCCO.
In entrambe le forme, il valore restituito è il valore dell'ultima
espressione valutata all'interno del mini-programma; può anche
essere usata un'istruzione return, proprio come per le subroutine.
L'espressione che fornisce il valore restituito, viene valutata in un
contesto vuoto, scalare oppure di lista, a seconda del contesto dell'eval
stesso. Si veda wantarray per maggiori informazioni su come può
essere valutata la valutazione del contesto.
Se ci fosse un errore di sintassi o un errore a tempo di esecuzione oppure
se venisse eseguita un'istruzione die
, eval
restituisce un valore
indefinito e in $@
viene posto il messaggio d'errore.
Se non ci fossero errori, $@
viene garantito essere una stringa nulla.
Fate attenzione al fatto che utilizzare eval
non impedisce al perl di
stampare gli avvertimenti su STDERR, né tantomeno il testo degli
avvertimenti viene memorizzato in $@
. Per fare entrambe le cose, dovete
usare l'agevolazione data da $SIG{__WARN__}
oppure disabilitare gli
avvertimenti all'interno del BLOCCO o ESPR utilizzando
no warnings 'all'
. Consultate warn, the perlvar manpage, the warnings manpage e
the perllexwarn manpage.
Va notato che, dato che eval
cattura gli errori altrimenti blocanti,
è utile per determinare se una particolare caratteristica (quale
socket
o symlink
) è implementata. È anche il
meccanismo di cattura delle eccezioni, dove l'operatore die viene usato
per sollevare le eccezioni.
Se il codice che deve essere eseguito non varia, potete usare la forma
eval-BLOCCO per catturare gli errori a tempo di esecuzione senza incorrere
nella penalizzazione di ricompilare ogni volta. L'errore, se c'è,
viene ancora restituito in $@
.
Esempi:
# rende la divisione per zero non bloccante eval { $risposta = $a / $b; }; warn $@ if $@;
# stessa cosa, ma meno efficiente eval '$risposta = $a / $b'; warn $@ if $@;
# un errore a tempo di compilazione eval { $risposta = }; # ERRATO
# un errore a tempo di esecuzione eval '$risposta ='; # imposta $@
Usare la forma eval{}
per catturare le eccezioni nelle librerie, presenta
qualche complicanza. A causa del corrente, opinabilmente non corretto, stato degli hook di
__DIE__
, potreste non voler innescare alcun hook
per quei __DIE__
che il codice utente potrebbe aver installato. Per
questo scopo si può utilizzare il costrutto local $SIG{__DIE__}
,
come mostrato in questo esempio:
# una trappola molto privata per l'eccezione divisione-per-zero eval { local $SIG{'__DIE__'}; $risposta = $a / $b; }; warn $@ if $@;
Questo ha un significato speciale, dato che gli hook di __DIE__
possono chiamare die
un'altra volta, e ciò ha l'effetto di
cambiare i loro messaggi d'errore:
# gli hook di __DIE__ pssono modificare i messaggi d'errore { local $SIG{'__DIE__'} = sub { (my $x = $_[0]) =~ s/pippo/pluto/g; die $x }; eval { die "pippo qua e` vivo" }; print $@ if $@; # stampa "pluto qua e` vivo" }
Visto che questo favorisce le azioni a distanza, questo comportamento non intuitivo sarà probabilmente risolto in una versione ventura.
Con un eval
, dovreste prestare particolare attenzione nel ricordare
cosa si sta esaminando quando:
eval $x; # CASO 1 eval "$x"; # CASO 2
eval '$x'; # CASO 3 eval { $x }; # CASO 4
eval "\$$x++"; # CASO 5 $$x++; # CASO 6
I casi 1 e 2 qua sopra, hanno un comportamento identico: essi eseguono
il codice contenuto nella variabile $x. (Sebbene il caso 2 ha delle
virgolette che sono ingannevoli che fanno sì che il lettore si
chieda cos'altro stia accadendno (nulla)). I casi 3 e 4, similmente,
si comportano allo stesso modo: eseguono il codice in '$x'
, che non fa
altro che restituire il valore di $x. (Il caso 4 è preferibile
solamente per ragioni visuali, ma ha anche il vantaggio di compilare a
tempo di compilazione invece che a tempo di esecuzione). Il caso 5
è un luogo dove, di norma, vorreste usare le virgolette,
eccetto che in questa particolare situazione, invece potete semplicemente
usare i riferimenti simbolici, proprio come nel caso 6.
eval BLOCCO
non viene considerata come un ciclo, dunque le
istruzioni di controllo di un ciclo next
, last
o redo
non
possono essere usate per lasciare o reiniziare il blocco.
Va notato che come caso davvero speciale, un eval ''
eseguito all'interno del
package DB
non vede l'usuale scope lessicale che lo circonda ma piuttosto lo scope
del primo pezzo di codice che non appartiene al package DB che l'ha chiamato. Di norma,
non si ha bisogno di preoccuparsi di questo a meno che non si stia scrivendo un
debugger del Perl.
exec
esegue un comando di sistema e non ritorna, usate
system
invece di exec
se volete che ritorni. Essa fallisce e
restituisce falso solo se il comando non esiste ed è eseguito
direttamente invece che tramite la shell dei comandi di sistema
(vedete qui sotto).
Poiché è un comune errore l'usare exec
invece di
system
, il Perl avvisa se non c'è un'istruzione che segue che
non sia die
, warn
o exit
(se viene impostato -w
, ma questo lo
si fa sempre). Se davvero si vuol far seguire exec
con qualche altra
istruzione, per evitare l'avvertimento si può usare una di queste
modalità:
exec ('pippo') or print STDERR "pippo non puo` essere eseguito: $!"; { exec ('pippo') }; print STDERR "pippo non puo` essere eseguito: $!";
Se ci fosse più di un argomento nella LISTA o se la LISTA è
un array con più di un valore, chiama execvp(3)
con gli
argomenti della LISTA. Se c'è solo un argomento scalare o un array
con un solo argomento, l'argomento viene esaminato alla ricerca di
metacaratteri di shell e, se presenti, l'intero argomento viene passato
alla shell dei comandi del sistema per l'analisi sintattica (questa
è /bin/sh -c
su piattaforme Unix ma può variare su altre
piattaforme). Se nell'argomento non ci sono metacaratteri di shell, esso
viene diviso in parole e passato direttamente a execvp
che è
più efficiente.
Esempi:
exec '/bin/echo', 'I vostri argomenti sono: ', @ARGV; exec "sort $file_in_output | uniq";
Se davvero non volete eseguire il primo argomento ma volete mentire al programma che si sta eseguendo riguardo al proprio nome, potete specificare il programma che si vuole realmente eseguire come un ``oggetto indiretto'' (senza alcuna virgola) davanti alla LISTA (Questo forza sempre l'interpretazione della LISTA come una lista multivalore anche se c'è solo un singolo scalare nella lista). Ad esempio:
$shell = '/bin/csh'; exec $shell '-sh'; # fa finta che sia una shell di login
oppure, più direttamente,
exec {'/bin/csh'} '-sh'; # fa finta che sia una shell di login
Quando gli argomenti vengono eseguiti attraverso la shell di sistema, i risultati saranno soggetti ai sui cavilli e alle sue capacità. Consultate `STRING` in the perlop manpage per i dettagli.
Usare un oggetto indiretto con exec
o system
è anche
più sicuro. Questo utilizzo (che funziona bene anche con
system())
forza l'interpretazione degli argomenti come fossero una
lista multivalore, anche se la lista avesse solo un argomento. In
questo modo siete al sicuro dalle wildcard [caratteri jolly, NdT]
di espansione della shell o dalla separazione delle parole che
contengono degli spazi.
@arg = ( "echo sorpresa" );
exec @arg; # soggetto agli escape della shell # if @args == 1 exec { $arg[0] } @arg; # sicuro anche con una lista di un arogmento
La prima versione, quella senza l'oggetto indiretto, ha eseguito il
programma echo passandogli un argomento "sorpresa"
. La seconda
versione non l'ha passato, essa ha provato ad eseguire un programma
chiamato letteralmente ``echo sorpresa'', non l'ha trovato e ha
impostato $?
ad un valore diverso da zero ad indicare il fallimento.
A partire dalla versione 5.6.0, il Perl cerca di terminare le operazioni
di I/O in corso su tutti i file aperti per l'output prima di eseguire
l'exec, ma questo potrebbe non essere supportato su alcune piattaforme
(consultate the perlport manpage). Per essere sicuri, dovreste impostare $|
($AUTOFLUSH nel modulo English) oppure chiamare il metodo autoflush()
di IO::Handle
su ogni handle aperto, per evitare di perdere l'output.
Va notato che exec
non chiamerà i vostri blocchi
END
né invocherà nessun metodo DESTROY
nei vostri oggetti.
print "Esiste\n" if exists $hash{$key}; print "Definito\n" if defined $hash{$key}; print "Vero\n" if $hash{$key};
print "Esiste\n" if exists $array[$index]; print "Definito\n" if defined $array[$index]; print "Vero\n" if $array[$index];
Un elemento di un hash o di un array può essere vero solo se è definito e definito solo se esiste, ma il viceversa non necessariamente mantiene il valore vero.
Data un'espressione che specifichi il nome di una subrotuine,
restituisce vero se la subroutine specificata è stata
dichiarata, anche se è indefinita. Menzionare il nome di
una subroutine per exists o defined non conta come il dichiararla.
Va notato che una subroutine che non esiste può essere
ancora richiamabile: il suo package potrebbe avere un metodo
AUTOLOAD
che lo fa nascere all'improvviso la prima volta che
viene chiamato, consultate the perlsub manpage.
print "Esiste\n" if exists &subroutine; print "Definito\n" if defined &subroutine;
Va notato che ESPR può essere arbitrariamente complicata finché l'operazione conclusiva è una ricerca della chiave di un hash o di un array o del nome di una subroutine:
if (exists $ref->{A}->{B}->{$chiave}) { } if (exists $hash{A}{B}{$chiave}) { }
if (exists $ref->{A}->{B}->[$ix]) { } if (exists $hash{A}{B}[$ix]) { }
if (exists &{$ref->{A}{B}{$chiave}}) { }
Sebbene l'array o l'hash più profondamente annidato non
nascerà all'improvviso solo perché la sua esistenza
è stata verificata, quelli intermedi lo faranno. Dunque
$ref->{"A"}
e $ref->{"A"}->{"B"}
nasceranno
all'improvviso a causa del test di esistenza per l'elemento
$chiave visto sopra. Questo avviene ovunque sia usato l'operatore
freccia, incluso anche:
undef $ref; if (exists $ref->{"Una qualche chiave"}) { } print $ref; # stampa HASH(0x80d3d5c)
Questa sorprendente autovivificazione in quello che non appare essere, ad una prima o anche seconda occhiata, un lvalue [valore a sinistra di un'espressione, NdT], potrebbe essere corretto in una versione futura.
Consultate Pseudo-hashes: Using an array as a hash in the perlref manpage
[``Pseudo-hash: Usare un array come un hash'', NdT] per le specifiche
su come exists()
si comporta quando usato su uno pseudo-hash.
L'uso di una chiamata a subroutine, invece che un nome di subroutine,
come argomento di exists()
è un errore.
exists ⊂ # OK exists &sub(); # Errore
$risp = <STDIN>; exit 0 if $risp =~ /^[Xx]/;
Date un'occhiata anche a die
. Se ESPR viene omessa, esce con
lo stato 0
. I soli valori universalmente riconosciuti per ESPR
sono 0
per il successo e 1
per l'errore; altri valori sono
soggetti ad interpretazione in relazione all'ambiente nel quale il
programma Perl è in esecuzione. Per esempio, uscire con un
69 (EX_UNAVAILABLE) da un filtro di sendmail per le mail in arrivo,
provocherà, da parte del programma che spedisce le mail, la
restituzione dell'oggetto che non è stato recapitato, ma
questo non è vero dappertutto.
Non usate exit
per interrompere una subroutine se c'è una
qualsiasi possibilità che qualcuno possa volere intercettare
quale che sia l'errore capitato. Usate die
invece, che può
essere intercettato da un eval
.
La funzione exit()
non esce sempre immediatamente. Essa chiama per
prima una qualunque delle routine END
definite, ma queste routine
END
non possono esse stesse interrompere l'uscita. Inoltre tutti i
distruttori dell'oggetto che devono essere chiamati, sono chiamati
prima dell'uscita vera e propria. Se questo fosse un problema, potete
chiamare POSIX:_exit($stato)
per evitare END e il processo di
distruzione. Consultate the perlmod manpage per i dettagli.
exp($_)
.
use Fcntl;
per ottenere le giuste definzioni delle costanti.
Il trattamento degli argomenti e la restituzione di
valore funziona come nella ioctl
più sotto.
Per esempio:
use Fcntl; fcntl($filehandle, F_GETFL, $packed_return_buffer) or die "impossibile eseguire fcntl F_GETFL: $!";
No dovete controllare il valore restituito da fnctl
con defined
.
Come ioctl
, esso mappa uno 0
restituito dalla chiamata di
sistema in uno "0 ma vero"
in Perl. Questa stringa è vera
in un contesto booleano e 0
in un contesto numerico. Essa viene anche
esonerata dal normale warning -w su una impropria conversione numerica.
Va notato che fcntl
produrrà un errore bloccante se usata
su un elaboratore che non implementa fcntl(2). Consultate il modulo Fcntl
o la manpage di fcntl(2)
per sapere quali funzioni sono disponibili sul
vostro sistema.
Ecco un esempio dell'impostazione di un filehandle chiamato REMOTE
ad
essere non bloccante a livello di sistema. Dovete tuttavia negoziare $|
voi stessi.
use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
$flag = fcntl(REMOTE, F_GETFL, 0) or die "Impossibile ottenere i flag per il socket: $!\n";
$flag = fcntl(REMOTE, F_SETFL, $flags | O_NONBLOCK) or die "Impossibile impostare i flag per il socket: $!\n";
select
e per operazioni POSIX di basso livello
sulla gestione dei tty. Se FILEHANDLE è un'espressione, il
valore viene considerato come filehandle indiretto, generalmente
il suo nome.
Potete usare questa funzione per verificare che due filehandle si riferiscano allo stesso descrittore:
if(fileno(QUESTO) == fileno(QUELLO)) { print "QUESTO e QUELLO sono duplicati\n"; }
(I filehandle collegati ad oggetti in memoria con le nuove
funzionalità di open
potrebbero restituire il valore
indefinito nonostante siano aperti).
fcntl(2)
oppure lockf(3).
flock
è l'interfaccia portabile del Perl al lock dei
file, sebbene esegua dei lock solo su interi file e non su record.
Due semantiche di flock
potenzialmente non ovvie ma tradizionali
sono che esso aspetta indefinitamente fino a che il lock non sia
assegnato e che i suoi lock sono solamente consultivi.
Tali lock discrezionali sono molto flessibili ma offrono minori
garanzie. Questo significa che i programmi che non usano anch'essi
flock
possono modificare quei file sottoposti a lock con
flock
. Per i dettagli consultate the perlport manpage, la vostra
specifica documentazione sul port oppure le vostre
manpage, specifiche del sistema. Se state scrivendo programmi
portabili, è meglio che assumiate un comportamento
tradizionale. (Ma se non lo state facendo, dovreste sempre sentirvi
perfettamente liberi di scrivere per le vostre idiosincrasie del
sistema (chiamate talvolta ``caratteristiche''). Pedisseque aderenze
agli interessi della portabilità non dovrebbero intralciare
nel portare il lavoro a termine).
OPERAZIONE è una di queste: LOCK_SH, LOCK_EX o LOCK_UN,
combinate eventualmente con LOCK_NB. Queste costanti sono
tradizionalmente i valori 1, 2, 8 e 4, ma potete usare i nomi
simbolici se li importate dal modulo Fcntl, sia indivudualmente
sia come gruppo, usando il tag ':flock'. LOCK_SH richiede un lock
condiviso, LOCK_EX richiede un lock esclusivo e LOCK_UN rilascia
un lock richiesto precedentemente. Se su LOCK_NB viene effettuato
un or a livello di bit con LOCK_SH o LOCK_EX, allora flock
terminerà immediatamente piuttosto che bloccare
aspettando il lock (controllate lo stato di ritorno per vedere
se lo avete ottenuto).
Per evitare la possibilità di una non coordinazione, ora il Perl svuota FILEHANDLE prima di effettuare un lock o un unlock su di esso.
Va notato che l'emulazione insita in lockf(3)
non fornisce lock
condivisi e richiede che FILEHANDLE sia aperto per scopi di
scrittura. Queste sono le semantiche che lockf(3)
implementa.
Tuttavia, molti se non tutti i sistemi implementano lockf(3)
in
termini del lock di fcntl(2), dunque le differenti semantiche
non dovrebbero infastidire troppe persone.
Va notato che l'emulazione fcntl(2)
di flock83) richiede che
FILEHANLDE sia aperto per scopi di lettura per usare LOCK_SH e
richiede che sia aperto per scopi di scrittura per usare LOCK_EX.
Va notato anche che alcune versioni di flock
non possono
effettuare lock su oggetti in rete; per questo caso sarebbe
necessario usiaste fcntl
che è più
specificatamente orientata al sistema. Se preferite, potete
forzare il Perl ad ignorare la vostra funzione flock(2)
di
sistema, e dunque fornire la vostra emulazione basata su
fcntl(2), passando l'opzione -Ud_flock
al programma
Configure quando si configura perl.
Ecco un un programma che aggiunge mail al file mailbox per sistemi BSD.
use Fcntl ':flock'; # importa le costanti LOCK_*
sub lock { flock(MBOX,LOCK_EX); # e, nel caso che qualcuno abbia aggiunto # mentre si era in attesa... seek(MBOX, 0, 2); }
sub unlock { flock(MBOX,LOCK_UN); }
open(MBOX, ">>/usr/spool/mail/$ENV{'USER'}") or die "Impossibile aprire mailbox: $!";
lock(); print MBOX $mess,"\n\n"; unlock();
Su sistemi che supportano un vero flock(), i lock sono ereditati attraverso le chiamate fork(), mentre quelli che devono ricorrere alla pià capricciosa funzione fcntl(), perdono i lock, rendendo pià difficoltoso lo scrivere server.
Consultate anche the DB_File manpage per altri esempi su flock().
0
al processo figlio,
oppure undef
se la chiamata non ha successo. I descrittori dei file (ed
a volte anche i lock su tali descrittori) vengono condivisi, mentre tutto
il resto viene copiato. Sulla maggior parte dei sistemi che supportano
fork(), l'efficienze è stata molto curata (per esempio, usando la
tecnologia copy-on-write [copia-su-scrittura, NdT] sulle pagine dati),
facendo di essa il paradigma dominante per il multitasking negli ultimi
decenni.
A partire dalla versione 5.6.0, Perl cercherà di completare le
operazioni di scrittura su tutti i file aperti in output prima di effettuare
il fork del processo figlio, ma ciò potrebbe non essere supportato
su alcuni sistemi (consultate the perlport manpage). Per essere sicuri, potreste
dover impostare $|
($AUTOFLUSH con il modulo English) o chiamare il
metodo autoflush()
di IO::Handle
sugli eventuali handle aperti,
così da evitare un output duplicato.
Se utilizzate fork
senza mai attendere i vostri figli, accumulerete
zombie. Su alcuni sistemi, potete evitare ciò impostando
$SIG{CHLD}
a "IGNORE"
. Consultate anche the perlipc manpage per ulteriori
esempi su fork e su come liberarsi dei figli moribondi.
Va notato che se il figlio che avrete creato con fork
eredita dei
descrittori di file di sistema come STDIN e STDOUT che sono in
realtà connessi da una pipe o un socket, anche se uscite, il
server remoto (come, ad esempio, uno script CGI o un processo in
background lanciato da una shell remota) non si accorgeranno che voi
avete finito. Se ciò rappresenta un problema, dovrete riaprire
tali descrittori verso /dev/null.
write
. Per esempio:
format Qualcosa = Test: @<<<<<<<< @||||| @>>>>> $str, $%, '$' . int($num) .
$str = "arnese"; $num = $costo/$quantita; $~ = 'Qualcosa'; write;
Consultate the perlform manpage per molti dettagli ed esempi.
format
,
tuttavia potete anche richiamarla. Essa formatta
(consultate the perlform manpage) una lista di valori in conformità
con i contenuti di DESCRIZIONE, ponendo l'output
nell'accumulatore del formato di output, $^A
(o
$ACCUMULATOR
con il modulo English). Infine, quando viene
eseguito un write
, i contenuti di $^A
vengono scritti su
qualche filehandle. Potreste anche leggere $^A
da
sé e poi reimpostare $^A
a ""
. Va notato che un
format tipicamente esegue un formline
per linea di formato
ma la funzione formline
di per sé non tiene conto di
quanti a capo sono inseriti nella DESCRIZIONE.
Questo significa che i token ~
e ~~
tratteranno l'intera
DESCRIZIONE come una singola linea. Perciò potreste
avere la necessità di usare formline multipli per
implementare un singolo record di formato, proprio come il
compilatore di formato.
Prestate attenzione se mettete tra virgolette doppie alla
descrizione, visto che un carattere @
può
assumere il significato di inzio del un nome di array.
formline
restituisce sempre vero. Consultate the perlform manpage
per altri esempi.
$!
). Se FILEHANDLE viene omesso, legge da
STDIN. Questo non è particolarmente efficiente.
Comunque, non può essere usata da se stessa per
prelevare dei singoli caratteri senza aspettare che l'utente
abbia premuto invio. Per questo, provate piuttosto qualcosa
come:
if ($STILE_BSD) { system "stty cbreak </dev/tty >/dev/tty 2>&1"; } else { system "stty", '-icanon', 'eol', "\001"; }
$tasto = getc(STDIN);
if ($STILE_BSD) { system "stty -cbreak </dev/tty >/dev/tty 2>&1"; } else { system "stty", 'icanon', 'eol', '^@'; # null ASCII } print "\n";
Determinare come deve essere impostato $STILE_BSD viene lasciato come esercizio al lettore.
La funzione POSIX::getattr
può fare questo in
maniera più portabile su sistemi che vogliono farsi
passare per essere conformi a POSIX. Date un'occhiata anche
al modulo Term::ReadKey
, dal più vicino sito
CPAN; dettagli su CPAN possono essere trovati su
CPAN in the perlmodlib manpage.
getpwuid
.
$login = getlogin || getpwuid($<) || "Kilroy";
Non prendete in considerazione getlogin
per l'autenticazione:
non è sicura quanto getpwuid
.
use Socket; $suosockaddr = getpeername(SOCK); ($porta, $indirizzo) = sockaddr_in($suosockaddr); $suohostname = gethostbyaddr($indirizzo, AF_INET); $suoindirizzo = inet_ntoa($indirizzo);
0
per ottenere il gruppo del processo corrente
per il processo corrente. Solleverà un'eccezione se usato
su elaboratori che non implementano getpgrp(2). Se PID viene
omesso, restituisce il gruppo del processo del processo corrente.
Va notato che la versione POSIX di getpgrp
non accetta un PID
come argomento, dunque solo PID==0
è davvero portabile.
Nota per gli utenti Linux: le funzioni C getpid()
e getppid()
implementate in Linux, restituiscono valori differenti se chiamate da
thread diversi. Per mantenere la portabilità, questo
comportamento non si riflette nella funzione Perl getppid()
, che
restituisce lo stesso valore anche se chiamata da thread diversi. Per
richiamare la funzione getppid()
di sistema si può utilizzare
il modulo CPAN Linux::Pid
.
($nome,$passwd,$uid,$gid, $quota,$commento,$gcos,$dir,$shell,$scadenza) = getpw* ($nome,$passwd,$gid,$members) = getgr* ($nome,$alias,$tipoind,$lungh,@indirizzi) = gethost* ($nome,$alias,$tipoind,$net) = getnet* ($nome,$alias,$proto) = getproto* ($nome,$alias,$porta,$proto) = getserv*
(Se la voce non esiste, otterrete una lista nulla).
L'esatto significato del campo $gcos varia ma di solito esso contiene il vero nome dell'utente (rispetto al nome del login) e altre informazioni pertinente all'utente. Fate attenzione, comunque, che su molti sistemi gli utenti sono in grado di cambiare queste informazioni e dunque ciò non può essere verificato e dunque $gcos è un dato potenzialmente dannoso (taint) (consultate the perlsec manpage). $passwd e $shell, la password cifrata dell'utente e la shell di login sono anch'esse dei dati potenzialmente dannosi per il medesimo motivo.
In contesto scalare, otterrete il nome a meno che la funzione non sia ottenuta con una ricerca per nome, nel qual caso otterrete l'altra cosa, qualunque essa sia (se l'elemento non esiste, otterrete il valore indefinito). Per esempio:
$uid = getpwnam($nome); $nome = getpwuid($num); $nome = getpwent(); $gid = getgrnam($nome); $nome = getgrgid($num; $nome = getgrent(); #ecc.
In getpw*(), i campi $quota, $commento e $scadenza sono casi
speciali nel senso che in molti sistemi non sono supportati. Se
$quota non è supportato, è uno scalare vuoto.
Se è supportato, di solito codifica il valore della quota
del disco. Se $commento non è supportato, è uno
scalare vuoto. Se è supportato di solito codifica dei
commenti amministrativi sull'utente. In alcuni sistemi il campo
$quota può essere $cambiamento oppure $eta, campi che
hanno a che fare con l'obsolescenza delle password. In alcuni
sistemi, il campo $commento può essere $classe. Il campo
$scadenza, se presente, codifica il periodo di scadenza dell'account
o della password. Per la disponibilità e l'esatto significato
di questi campi nel vostro sistema, consultate la documentazione di
getpwnam(3)
e il file pwd.h. Potete anche scoprire dall'interno
del Perl che significato hanno i vostri $quota e $commento e se
possedete il campo $expire, tramite l'utilizzo del modulo Config
e
i valori d_pwquota
, d_pwage
, d_pwchange
, d_pwcomment
e
d_pwexpire
. I file con le password shadow sono supportati solo se
l'azienda produttrice di software che vi fornisce li ha implementati
in quel modo intuitivo che, chiamando le routine della libreria C
usuale, ottiene le versioni shadow se siete in esecuzione con i
privilegi o se esistono le funzioni shadow(3)
come si trovano in
System V (questo include Solaris e Linux). Quei sistemi che
implementano un'infrastruttura proprietaria per le password shadow
è improbabile che siano supportati.
Il valore di $members restituito da getgr*() è una lista separata da spazi dei nomi di login dei membri del gruppo.
Per le funzioni gethost*(), se la variabile h_errno
è supportata in C, vi sarà
restituita attraverso $?
se la chiamata di funzione fallisce. Il valore @addrs
restituito da
una chiamata che ha avuto successo è una lista di indirizzi grezza, restituita dalla
corrispondente chiamata della libreria di sistema. In ambito Internet, ogni indirizzo è
lungo 4 byte e potete effetturare unpack su esso scrivendo qualcosa come:
($a,$b,$c,$d) = unpack('C4',$ind[0]);
La libreria Socket rende questo un po' più facile:
use Socket; $indint = inet_aton("127.1"); # o qualsiasi indirizzo $nome = gethostbyaddr($indint, AF_INET);
# oppure andando nell'altro verso $strind = inet_ntoa($indint);
Se siete stanchi di tenere a mente quali valori corrispondono a quali elementi della lista
restituita, vengono fornite delle interfaccie per nome nei moduli standard: File::stat
,
Net::hostent
, Net::netent
, Net::protoent
, Net::servent
, Time::gmtime
, Time::localtime
e User::grent
. Queste si sovrappongono alle normali funzioni interne, fornendo versioni che
restituiscono oggetti con i nomi appropriati per ogni campo. Per esempio:
use File::stat; use User::pwent; $suo = (stat($nomefile)->uid == pwent($chiunque)->uid);
Anche se sembra che siano gli stessi metodi di chiamata (uid), non lo sono perché un oggetto
File::stat
è diverso da un oggetto User::pwent
.
use Socket; $miosockaddr = getsockname(SOCK); ($porta, $mioind) = sockaddr_in($miosockaddr); printf "Connesso a %s [%s]\n", scalar gethostbyaddr($mioind, AF_INET), inet_ntoa($mioind);
Socket
). Per consultare le opzioni
ad un altro livello, dovrebbe venir fornito il numero di protocollo dell'appropriato
protocollo che controlla l'opzione. Per esempio, per indicare che un'opzione sarà
interpretata dal protocollo TCP, LIVELLO dovrà essere impostato come numero di
protocollo di TCP, che potete ottenere usando getprotobyname.
La chiamata restituisce una stringa compattata che rappresenta l'opzione del socket richiesta,
oppure undef
se c'è un errore (il motivo dell'errore sarà in $!). Quello che
c'è esattamente nella stringa compattata dipende da LIVELLO e NOMEOPZ, consultate la
vostra documentazione di sistema per i dettagli. Comunque, un caso molto comune è che
l'opzione sia un intero, nel qual caso il risultato sarà un intero compattato che
potete decodificare usando unpack con il formato i
(o I
).
Un esempio che testa se l'algoritmo di Nagle sia attivato su di un socket:
use Socket qw(:all);
defined(my $tcp = getprotobyname("tcp")) or die "Non posso determinare il numero di protocollo per tcp"; # my $tcp = IPPROTO_TCP; # Alternativo my $compattato = getsockopt($socket, $tcp, TCP_NODELAY) or die "Non posso interrogare l'opzione TCP_NODELAY del socket: $!"; my $senzaritardo = unpack("I", $compattato); print "L'algoritmo di Nagle e`", $senzaritardo ? "non attivato\n" : "attivato\n";
<*.c>
, ma potete usarla direttamente.
Se ESPR viene omessa, glob()
utilizza $_
. L'operatore <*.c>
è discusso in maggiore dettaglio in I/O Operators in the perlop manpage
[``Operatori di I/O'', NdT].
A partire dalla versione 5.6.0, questo operatore è implementato
utilizzando l'estensione standard File::Glob
. Consultate
the File::Glob manpage per i dettagli.
# 0 1 2 3 4 5 6 7 8 ($sec,$min,$ore,$giom,$mese,$anno,$gios,$gioa,$oraleg) = gmtime(time);
Tutti gli elementi della lista sono numerici, e derivano direttamente dalla
'struct tm' del C. $sec, $min e $ore sono i secondi, i minuti e le ore
dell'orario specificato. $giom è il giorno del mese, e $mese è
il mese stesso, nell'intervallo 0..11
, in cui 0 indica Gennaio e 11 Dicembre.
$anno è il numero di anni a partire dal 1900. Ciò significa che
$anno è 123
nel 2023. $gios è il giorno della settimana, con 0
che indica Domenica e 3 Mercoledì. $gioa è il giorno dell'anno,
nell'intervallo 0..364
(o <0..365> negli anni bisestili). $isdst
è sempre 0
.
Va notato che l'elemento $anno non contiene semplicemente le ultime due cifre dell'anno. Se assumete ciò, allora vi ritrovate a creare programmi non compatibili con l'anno 2000 (Y2K), e questo non volete farlo, vero?
Il modo corretto per ottenere un anno a 4 cifre è semplicemente:
$anno += 1900;
E per ottenere le ultime due cifre dell'anno (ad esempio '01' nel 2001) potete scrivere:
$anno = sprintf("%02d", $anno % 100);
Se ESPR viene omessa, gmtime()
usa l'ora correte (gmtime(time)
).
In contesto scalare, gmtime()
restituisce il valore di ctime(3):
$stringa_diadesso = gmtime; # es. "Thu Oct 13 04:54:34 1994"
Se vi serve il tempo locale invece del GMT, usate la funzione localtime che è
integrata in Perl.
Consultate anche la funzione timegm
fornita dal modulo Time::Local
,
e le funzioni strftime(3)
e mktime(3)
disponibili attraverso il modulo the POSIX manpage.
Questo valore scalare non dipende dal locale (consultate the perllocale manpage), ma è interno a Perl. Per ottenere stringhe di data simili, ma dipendenti dal locale, consultate gli esempi in localtime.
Si consulti gmtime in the perlport manpage per ciò che concerne la portabilità.
goto-ETICHETTA
trova l'istruzione etichettata con ETICHETTA e
riprende l'esecuzione da essa. Questa forma non può essere
utilizzata per entrare in alcun costrutto che richieda inizializzazione,
come una subroutine oppure un loop foreach
. Inoltre, non può
essere utilizzata per entrare in un costrutto che è eliminato in
fase di ottimizzazione o per uscire da un blocco o da un subroutine
passata a sort
. Può essere utilizzato per saltare praticamente
in qualsiasi altro posto all'interno dello scope dinamico, anche fuori
dalle subroutine, ma di solito è meglio utilizzare qualche altro
costrutto, come last
o die
. L'autore di Perl non ha mai sentito la
necessità di servirsi di questa forma di goto
(in Perl,
appunto, C è un'altra questione). (La differenza è che C
non offre loop provvisti di nome in combinazione al controllo sui loop.
Perl lo fa, e ciò sostituisce la maggior parte degli usi
strutturati di goto
negli altri linguaggi).
La forma goto-ESPR
si attende un nome di etichetta, il cui scope viene
poi risolto dinamicamente. Questo permette l'utilizzo dei goto
calcolati
di FORTRAN, ma non è consigliato se state ottimizzando al fine di
creare codice manutenibile:
goto ("PIPPO", "PLUTO", "PAPERINO")[$i];
La forma goto-&NOME
è piuttosto diversa dalle altre forme di
goto
. In realtà non è affatto un goto nel suo significato
normale, e non ha le croci associate agli altri goto. Invece, esce dalla
subroutine corrente (causando la perdita di eventuali modifiche eseguite da
local())
e chiama immediatamente la subroutine indicata utilizzando il
valore corrente di @_. Questa forma è utilizzata dalle subroutine
AUTOLOAD
che desiderano caricare un'altra subroutine e poi far credere
che sia stata quest'ultima ad essere chiamata sin dall'inizio (tuttavia
eventuali modifiche a @_
effettuate dalla subroutine corrente vengono
propagate all'altra). Dopo il goto
, nemmeno caller
sarà in
grado di dire che questa subroutine è stata chiamata per prima.
Non è necessario che NOME sia il nome di una subroutine; può essere una variabile scalare contenente un riferimento a codice, oppure un blocco che fornisce un riferimento a codice.
grep(1)
e ai suoi congiunti. In particolare, non è
limitata all'uso di espressioni regolari.
Valuta il BLOCCO o l'ESPR per ogni elemento
della LISTA (assegnando localmente a $_
ogni
elemento) e restituisce una valore di lista costituito
da quegli elementi per i quali la valutazione
dell'espressione restituisce il valore vero. In un
contesto scalare, restituisce il numero di volte
che l'espressione ha restituito valore vero.
@pippo = grep(!/^#/, @pluto); # spazza via i commenti
o equivalentemente,
@pippo = grep {!/^#/} @pluto; # spazza via i commenti
Va notato che $_
è un alias del valore
dell'elemento della lista, quindi può essere
usato per modificare elementi della LISTA. Benché
utile e supportato, può causare risultati
bizzarri se gli elementi della LISTA non sono variabili.
Allo stesso modo, grep restituisce alias agli elementi
della lista originale, in modo molto simile a quello in cui
il ciclo for costruisce alias per gli elementi della lista.
Per questa ragione modificare un elemento della lista
restituita da grep (ad esempio in un foreach
, in un
map
o in un altro grep
) di fatto modifica l'elemento
della lista originale. è qualcosa che di solito si
dovrebbe evitare scrivendo codice chiaro.
Consultate anche map per una lista composta dai risultati del BLOCCO o dell'ESPR.
0
, 0x
o 0b
,
date un'occhiata a oct). Se ESPR viene omessa, hex()
usa $_
.
print hex '0xAf'; # stampa '175' print hex 'aF'; # stessa cosa
Le stringhe esadecimali possono rappresentare solo numeri interi. Le
stringhe che causerebbero un overflow generano un avvertimento. A
differenza di oct(), hex()
non rimuove eventuali spazi bianchi ad inizio
stringa. Per mostrare qualcosa come esadecimale, si dia un'occhiata a printf,
sprintf o unpack.
import
. Si tratta semplicemente di un
normale metodo (subroutine) definito (o ereditato) dai moduli che
desiderano esportare dei nomi in un altro modulo. La funzione use
chiama il metodo import
per il package usato. Consultate anche use,
the perlmod manpage e the Exporter manpage.
index
inizia a cercare dall'inizio della stringa.
La POSIZIONE prima dell'inizio della stringa oppure dopo la sua fine
viene trattata come se fosse, rispettivamente, l'inizio o la fine.
POSIZIONE ed il valore restituito indicano la posizione a partire da 0
(o
qualsiasi valore a cui abbiate impostato la variabile $[
, ma non fatelo).
Se la sottostringa non viene trovato, index
restituisce un'unità
meno della base, cioè solitamente -1
.
int()
usa $_
.
Questa funziona non va usata per arrotondare: primo perché tronca
verso 0
, e secondo perché le rappresentazioni della macchina dei
numeri in virgola mobile possono dar luogo a risultati inaspettati. Per
esempio, int(-6.725/0.025)
generara -268 anziché il corretto -269;
ciò è dovuto al fatto che il numero è in
realtà qualcosa di simile a -268.99999999999994315658. Di solito, le
funzioni sprintf
, printf
, o POSIX::floor
e POSIX::ceil
vi
saranno più utili di quanto possa esserlo int().
require "sys/ioctl.ph"; # probabilmente in $Config{archlib}/sys/ioctl.ph
per ottenere le corrette definizioni delle funzioni. Se sys/ioctl.ph
non esiste oppure non contiene le corrette definizioni, dovrete
scrivervele da soli, basandovi sui file header in C, come ad esempio
<sys/ioctl.h >>. (C'è uno script Perl chiamato h2ph,
fornito assieme al kit Perl, che potrebbe aiutarvi in questo, ma la cosa
non è così banale). SCALARE verrà letto e/o scritto a seconda
della FUNZIONE, un puntatore al valore della stringa contenuta in
SCALARE verrà passato come terzo argomento della reale chiamata
a ioctl
. (Se SCALARE non ha un valore di stringa ma ne ha uno
numerico, verrà passato direttamente tale valore anziché
un puntatore al valore della stringa. Per garantire che ciò
avvenga, aggiungete uno 0
allo scalare prima di utilizzarlo).
Potrebbe risultare necessario ricorrere alle funzioni pack
e
unpack
per manipolare i valori delle strutture utilizzate da
ioctl
.
Il valore restituito da ioctl
(e fnctl
) è di seguito
descritto:
se l'SO restituisce: allora Perl restituisce: 1 valore indefinito 0 stringa "0 ma vera" qualsiasi altra cosa quel numero
Dunque, Perl restituisce vero in caso di successo e falso in caso di fallimento. In ogni caso potete determinare facilmente il reale valore restituito dal sistema operativo:
$valorerit = ioctl(...) || -1; printf "Il sistema ha restituito %d\n", $valorerit;
La stringa speciale "0 ma vero"
non risente delle proteste
di -w sulla conversione impropria dei numeri.
$record = join(':', $login,$passwd,$uid,$gid,$gcos,$home,$shell);
Fate attenzione al fatto che a differenza di split
,
join
non accetta un pattern come primo argomento.
Fate il confronto con split.
Le chiavi sono restituite in ordine apparentemente casuale. Tale ordine casuale
sarà soggetto a cambiamenti nelle future versioni di perl, ma
è garantito essere lo stesso che restituiscono le funzioni
values
e each
(ponendo che l'hash non sia stato modificato).
Per ragioni di sicurezza, a partire dal Perl 5.8.1 l'ordinamento
è differente anche tra diverse esecuzioni di Perl (consultate
Algorithmic Complexity Attacks in the perlsec manpage [``Attacchi di Complessità Algoritmica'', NdT]).
Come effetto collaterale, la chiamata a keys()
reimposta l'iteratore interno dell'HASH
(si veda each). In particolare, una chiamata a keys()
in un contesto vuoto, reimposta
l'iteratore senza alcun costo computazionale aggiuntivo.
Ecco ancora un altro modo per stampare le variabili d'ambiente:
@chiavi = keys %ENV; @valori = values %ENV; while (@chiavi) { print pop(@chiavi), '=', pop(@valori), "\n"; }
oppure ordinate per chiave:
foreach $chiave (sort(keys %ENV)) { print $chiave, '=', $ENV{$chiave}, "\n"; }
I valori restituiti sono copie delle chiavi originali nell'hash, dunque modificare esse non modifica l'hash originale. Fate il confronto con values.
Per ordinare un hash per valore, dovrete utilizzare una funzione
sort
. Ecco un ordinamento numerico decrescente di un hash,
secondo i suoi valori:
foreach $chiave (sort { $hash{$b} <=> $hash{$a} } keys %hash) { printf "%4d %s\n", $hash{$chiave}, $chiave; }
Utilizzata come lvalue [valore a sinistra di un'espressione, NdT],
keys
vi permette di incrementare il numero di spazi allocati
per l'hash indicato. Questo può risultare uno strumento
efficiente, se sapete quanto diventerà grande l'hash.
(è simile alla pre-estensione di un array tramite
l'assegnazione di un numero più grande a $#array).
Se scrivete:
keys %hash = 200;
allora %hash
avrà almeno 200 spazi allocati per esso,
256 in realtà, poiché arrotonda alla successiva
potenza di due. Questi spazi saranno mantenuti anche se scrivete
%hash = ()
, usate undef %hash
se volete liberare lo spazio
in memoria quando %hash
è ancora nello scope. Non
potete ridurre il numero di spazi allocati per l'hash utilizzando
keys
in questo modo (ma non dovrete preoccuparvi del fare
ciò per sbaglio, poiché il tentativo non ha alcun
effetto collaterale).
$conta = kill 1, $figlio1, $figlio2; kill 9, @morituri;
Se SEGNALE è zero, il processo non riceve nessun segnale. Questo rappresenta un utile modo di verificare che il processo sia ancora attivo e non abbia cambiato il suo UID. Consultate the perlport manpage per le note sulla portabilità di questo costrutto.
Diversamente da quanto accade nella shell, se SEGNALE è negativo, vengono terminati gruppi di processi invece di processi (su sistemi basati su System V, un numero di PROCESSO negativo ha lo stesso effetto di terminare gruppi di processi, ma questo non è portabile). Questo significa che generalmente vanno utilizzati segnali positivi, non negativi. Si può anche utilizzare un nome di processo fra virgolette.
Consultate Signals in the perlipc manpage [``Segnali'', NdT] per maggiori dettagli.
last
è come l'istruzione break
del C (che viene
utilizzata nei loop); esce immediatamente dal loop in questione. Se
l'ETICHETTA viene omessa, il comando fa riferimento al ciclo più
interno che la racchiude. Il blocco continue
, se presente, non
viene eseguito:
LINEA: while (<STDIN>) { last LINEA if /^$/; # esce alla fine degli header #... }
last
non può essere utilizzato per uscire da un blocco che
restituisce un valore, come eval {}
, sub {}
o do {}
, e non
dovrebbe essere utilizzato per uscire da un'operazione grep()
o map().
Va notato che un blocco, in sé, è semanticamente
identico ad un loop che viene eseguito una volta sola. Quindi, last
può essere utilizzato per ottenere un'uscita anticipata da un
blocco.
Consultate anche continue per un esempio di come funzionano last
, next
e redo
.
\L
nelle stringhe tra apici doppi.
Rispetta l'LC_CTYPE locale corrente se use locale
é attivo.
Consultate the perllocale manpage e the perlunicode manpage per maggiori dettagli sul supporto
per il locale e l'Unicode.
Se ESPR viene omessa, lc usa $_
.
\l
nelle stringhe racchiuse tra apici doppi. Rispetta il locale LC_CTYPE corrente
se è stato specificato use locale
. Consultate the perllocale manpage e
the perlunicode manpage per maggiori dettagli sul supporto per il locale e l'Unicode.
Se ESPR viene omessa, la funzione usa $_
.
$_
. Va notato che questa funzione
non può essere usata su interi array o hash per scoprire quanti
elementi essi abbiano. Per questo, usate rispettivamente scalar @array
e scalar keys %hash
.
Notate i caratteri: se la ESPR è in Unicode, otterrete il
numero di caratteri, non il numero di byte. Per ottenere la lunghezza in
byte, usate do { use bytes; length(ESPR) }
, consultate the bytes manpage.
my
, poiché
local
non è ciò che la maggior parte delle persone
intendono come ``locale''. Consultate Private Variables via my() in the perlsub manpage
[``Variabili private tramite my()'', NdT] per dettagli.
Local modifica le variabili indicate e le rende locali al blocco, file o eval
che include la chiamata. Se viene indicato più di un valore, la lista
deve essere posta tra parentesi. Consultate Temporary Values via local() in the perlsub manpage
[``Valori temporanei tramite local()'', NdT] per dettagli, incluse le problematiche
relative agli array ed agli hash legati [con tie
, NdT].
# 0 1 2 3 4 5 6 7 8 ($sec,$min,$ore,$giom,$mese,$anno,$gios,$gioa,$oraleg) = localtime(time);
Tutti gli elementi della lista sono numerici, e derivano direttamente dalla
'struct tm' del C. $sec
, $min
e $ore
sono i secondi, i minuti e le ore
dell'orario specificato.
$giom
è il giorno del mese, e $mese è il mese stesso,
nell'intervallo 0..11
, in cui 0 indica Gennaio e 11 Dicembre.
Ciò rende facile ottenere il nome di un mese da una lista:
my @abbr = qw( Gen Feb Mar Apr Mag Giu Lug Ago Set Ott Nov Dic ); print "$abbr[$mese] $giom"; # $mese=9, $giom=18 fornisce "Ott 18"
$anno
è il numero di anni a partire dal 1900, non solo le ultime due cifre
dell'anno. Ciò significa che $anno
è 123
nel 2023. Il modo corretto per
ottenere un anno a quattro cifre è semplicemente:
$anno += 1900;
Per ottenere le ultime due cifre dell'anno (ad esempio, '01' in 2001) fate:
$anno = sprintf("%02d", $anno % 100);
$gios
è il giorno della settimana, con 0 che indica Domenica e 3 Mercoledì.
$gioa
è il giorno dell'anno, nell'intervallo 0..364
(o <0..365> negli anni bisestili).
$oraleg
assume valore vero se l'orario specificato cade durante l'ora legale,
valore falso altrimenti.
Se ESPR viene omessa, localtime()
usa l'ora correte (localtime(time)
).
In contesto scalare, localtime()
restituisce il valore di ctime(3):
$stringa_diadesso = localtime; # es. "Thu Oct 13 04:54:34 1994"
Questo valore scalare non dipende dal locale ma è interno a Perl.
Per il GMT invece del tempo locale, utilizzate la funzione interna gmtime.
Consultate anche il modulo Time::Local
(per riconvertire secondi, minuti, ore, ...
nel valore intero restituito da time())
e le funzioni strftime(3)
e mktime(3)
del modulo the POSIX manpage.
Per ottenere stringhe di data simili, ma dipendenti dal locale, impostate le vostre variabili d'ambiente relative al locale in maniera appropriata (consultate the perllocale manpage) e provate ad esempio:
use POSIX qw(strftime); $stringa_diadesso = strftime "%a %b %e %H:%M:%S %Y", localtime; # oppure per il GMT formattato in maniera appropriata per il vostro locale: $stringa_diadesso = strftime "%a %b %e %H:%M:%S %Y", gmtime;
Va notato che gli escape %a
e %b
, che rappresentano la forma abbreviata
del giorno della settimana e del mese dell'anno, possono non essere
necessariamente lunghi tre caratteri.
Si consulti localtime in the perlport manpage per ciò che concerne la portabilità.
lock()
è una ``parola chiave debole'': questo significa che se avete
definito una funzione con questo nome (prima di qualsiasi chiamata ad essa),
sarà invece questa funzione ad essere chiamata. (Ad ogni modo, se
dichiarate use threads
, lock()
è sempre una parola chiave).
Consultate the threads manpage.
$_
. Per ottenere il logaritmo in un'altra base,
servitevi dell'algebra di base: il logaritmo in base N di un numero corrisponde
al logaritmo naturale di quel numero diviso per il logaritmo naturale di N.
Ad esempio:
sub log10 { my $n = shift; return log($n)/log(10); }
Consultate anche exp per l'operazione inversa.
stat
(compreso impostare lo speciale
filehandle _
) ma esegue stat
su di un link simbolico invece che sul
file al quale il link simbolico punta. Se sul vostro sistema i link
simbolici non sono implementati, viene eseguita una normale /stat
.
Per informazioni molto più dettagliate, consultate la documentazione di stat.
$_
ogni elemento)
e restituisce la lista di valori costituita dai
risultati di ciascuna di queste valutazioni. In un
contesto scalare, restituisce il numero il numero totale
degli elementi così generati. Valuta
il BLOCCO o l'ESPR in un contesto di lista, in
maniera tale che ciascuno degli elementi della LISTA
può produrre zero, uno o più elementi
nel valore restituito.
@caratteri = map(chr, @numeri);
traduce una lista di numeri nei corrispondenti caratteri. E
%hash = map { getkey($_) => $_ } @array;
è solo un modo divertente per scrivere:
%hash = (); foreach $_ (@array) { $hash{getkey($_)} = $_; }
Va notato che $_
è un alias del valore
dell'elemento della lista, quindi può essere
usato per modificare elementi della LISTA. Benché
utile e supportato, può causare risultati
bizzarri se gli elementi della LISTA non sono variabili.
L'uso di un regolare ciclo foreach
per questi scopi
sarebbe più chiaro nella maggior parte dei casi.
Consultate anche grep per un array costituito da
quegli elementi della lista originale per i quali
la valutazione del BLOCCO o dell'ESPR produce un valore
vero.
Con {
cominciano sia i blocchi che i riferimenti a
hash, quindi map { ...
può essere sia l'inizio
di map BLOCK LIST che l'inizio di map EXPR, LIST.
Poichá perl non guarda avanti alla ricerca della
}
di chiusura, deve formulare una congettura a
proposito di ciò con cui ha a che fare, basandosi
su quello che trova subito dopo {
.
Tipicamente indovina, ma in caso contrario non
capirà che qualcosa non va fino a quando non
arriverà alla }
, trovando una virgola di troppo
(o mancante). L'errore sintattico sarà
segnalato vicino alla }
ma dovrete cambiare qualcosa
vicino alla {
, ad esempio usare un +
unario
per aiutare un pochino il perl:
%hash = map { "\L$_", 1 } @array # perl crede sia una ESPR. sbagliato %hash = map { +"\L$_", 1 } @array # perl crede sia un BLOCCO. giusto %hash = map { ("\L$_", 1) } @array # anche questo funziona %hash = map { lc($_), 1 } @array # cosi` come questo %hash = map +( lc($_), 1 ), @array # questa e` una ESPR e funziona!
%hash = map ( lc($_), 1 ), @array # viene valutato in (1, @array)
oppure, per forzare un costruttore di hash anonimi, usate +{
@tanti_hash = map +{ lc($_), 1 }, @array # e` un'ESPR, quindi ha bisogno della , in fondo
e otterrete una lista di hash anonimi, ciascuno con una sola coppia chiave/valore.
umask
). In caso di successo
restituisce vero, altrimenti restituisce falso ed imposta $!
(errno). Se omesso, MASK assume valore 0777.
In generale, è meglio creare le directory utilizzando MASK
permissive, e poi consentire all'utente di modificarle con il suo
umask
, piuttosto che fornire una MASK restrittiva e non offrire
all'utente alcuna possibilità per renderla più permissiva.
L'eccezione a questa regola si ha nel caso in cui il file o la directory
debbano essere mantenuti privati (ad esempio file contenenti posta).
La voce di perlfunc(1)
su umask
discute la scelta di una MASK in
maniera piuù dettagliata.
Va notato che, in accordo con la specifica POSIX 1003.1-1996, NOMEFILE può avere come suffisso un numero qualsiasi di slash. Alcuni sistemi operativi non gestiscono questa cosa correttamente, quindi Perl rimuove in automatico tutti gli slash alla file di NOMEFILE, facendo contenti tutti.
msgctl(2)
del System V IPC. Probabilmente dovrete prima scrivere
use IPC::SysV;
per ottenere le corrette definizioni delle costanti. Se CMD è IPC_STAT
, allora
ARG deve essere una variabile, che conterrà la struttura msqid_ds
restituita.
I valori restituiti sono gli stessi di ioctl
: il valore indefinito in caso di errore,
"0 ma vero"
in caso di zero, il reale valore restituito negli altri casi. Consultate
anche la documentazione di SysV IPC in the perlipc manpage, IPC::SysV
e IPC::Semaphore
.
msgget(2)
del System V IPC. Restituisce l'id della coda dei messaggi,
oppure il valore indefinito se si verifica un errore. Consultate anche la documentazione
di SysV IPC in the perlipc manpage, IPC::SysV
e IPC::Msg
.
unpack("l! a*")
. Questo provoca un taint sulla variabile [il dato in essa contenuto
viene indicato come potenzialmente dannoso, NdT].
Restituisce vero in caso di successo, oppure falso se si verifica un errore.
Consultate anche la documentazione di SysV IPC in the perlipc manpage, IPC::SysV
e
IPC::SysV::Msg
.
pack("l! a*", $tipo, $messaggio)
. Restituisce vero in caso di successo, o falso se si
verifica un errore. Consultate anche la documentazione di IPC::SysV
e
IPC::SysV::Msg
.
my
dichiara le variabili indicate, come locali (a livello lessicale) nel blocco,
file o eval
, che include la dichiarazione. Se viene indicata più di una
variabile, la lista va messa tra parentesi.
Le precise semantiche e l'interfaccia di TIPO ed ATTR sono ancora in evoluzione. TIPO
è al momento legato all'uso della direttiva fields
, e gli attributi sono gestiti
utilizzando la direttiva attributes
oppure, a partire da Perl 5.8.0, anche servendosi del
modulo Attribute::Handlers
. Consultate Private Variables via my() in the perlsub manpage
[``Variabili private tramite my()'', NdT] per dettagli e the fields manpage, the attributes manpage e
the Attribute::Handlers manpage.
next
è come l'istruzione continue
in C; avvia l'iterazione
successiva del ciclo:
LINEA: while (<STDIN>) { next LINEA if /^#/; # scarta i commenti #... }
Va notato che se ci fosse un blocco continue
nel precedente esempio, si otterrebbe
l'esecuzione anche delle linee scartate. Se l'ETICHETTA viene omessa, il comando fa
riferimento al ciclo più interno che la racchiude.
next
non può essere usato per uscire da un blocco che restituisce un valore
come eval {}
, sub {}
o do {}
e non dovrebbe essere usato per uscire da una
operazione di grep()
o map().
Va notato che un blocco di per sé è semanticamente identico ad un ciclo
che viene eseguito una volta sola. Perciò next
uscirà in maniera
anticipata da un tale blocco.
Date un'occhiata anche a continue per una delucidazione su come funzionano last
,
next
e redo
.
use
, della quale no
è l'opposto.
0x
, viene interpretata come
una stringa esadecimale. Se ESPR inizia con 0b
, viene interpretata come
una stringa binaria. Qualsiasi spazio bianco che faccia da prefisso viene
ingnorato in tuti e tre i casi). Il seguente codice è in grado di
gestire decimali, binari, ottali ed esacimali nella notazione standard di
Perl o di C:
$val = oct($val) if $val =~ /^0/;
Se ESPR viene omessa, oct()
usa $_
. Per compiere l'operazione inversa
(produrre un numero ottale), usate sprintf()
o printf():
$permessi = (stat("nomefile"))[2] & 07777; $permessi_ottali = sprintf "%lo", $permessi;
La funzione oct()
è comunemente usata quando una stringa come 644
necessita di essere convertita affinché rappresenti per, esempio, i
permessi di un file. (Benché perl converta automaticamente le stringhe
in numeri quando necessario, questa conversione automatica usa la base 10).
(Quella che segue èegue una documentazione completa di open(): per un'introduzione più semplice prendete in considerazione la lettura the perlopentut manpage).
Se FILEHANDLE è una variabile scalare non definita (oppure un
elemento di un array o di un hash), le viene assegnato un riferimento
ad un filehandle anonimo, diversamente se FILEHANDLE è
un'espressione, il suo risultato è usato come nome del
filehandle voluto. (Questo potrebbe esser considerato
come un riferimento simbolico, in questo caso use strict 'refs'
potrebbe non essere efficace).
Se EXPR viene omesso, verrà usata la variabile come scalare
dello stesso nome di FILEHANDLE. (Si noti che le variabili lessicali,
quelle dichiarate con my
, non funzioneranno per questo scopo;
in questo caso se usate my
, specificate ESPR nella chiamata a open).
Se vengono specificati tre o più argomenti la modalità
di apertura e il nome del file sono separati. Se MODE è '<'
oppure nulla, il file è aperto in lettura. Se MODE è
'>'
il file viene troncato e aperto in scrittura, oppure creato
se necessario. Se MODE è '>>'
il file viene aperto in
append mode oppure creato se necessario [``append mode'' significa
scrittura dalla fine del file, NdT].
Potete mettere un '+'
davanti a '>'
oppure '<'
per
indicare che intendete sia leggere che scrivere sul file; per questo
'+<'
è quasi sempre preferito per aggiornamenti in
lettura/scrittura, la modalità '+>'
prima
troncherà il file. Di norma non potete usare la modalità
di lettura/scrittura per aggiornare file di testo, dato che hanno una
lunghezza di record non fissa. Controllate l'opzione -i in the perlrun manpage
per un miglior approccio al problema. Il file viene creato con permessi
0666
modificati dalla umask
impostata per il processo.
Questi vari prefissi corrispondono ai parametri mode di fopen(3)
'r'
,
'r+'
, 'w'
, 'w+'
, 'a'
e 'a+'
.
Nel caso d'uso a 2 argomenti (e 1 argomento) il MODE e il FILENAME devono
essere concatenati (nel modo citato), possibilmente separati da spazi.
Non è possibile omettere il MODE in questi casi se si intende
usare '<'
.
Se il FILENAME inizia per '|'
verrà interpretato come un comando
al quale gli verrà inviato dell'output come pipe, e se FILENAME
finisce per '|'
verrà interpretato come un comando che invierà
il suo output a noi. Consultate Using open() for IPC in the perlipc manpage [``Usare open()
per IPC'', NdT]
per altri esempi su questo caso. (Non è ammesso l'uso di open
per eseguire un
comando e accedervi in scrittura e in lettura, consultate the IPC::Open2 manpage,
the IPC::Open3 manpage e Bidirectional Communication with Another Process in the perlipc manpage
[``Comunicazioni bidirezionali con un altro processo'', NdT] per delle alternative).
Per tre o più argomenti, se MODO è '|-'
, il nome del file viene
interpretato come un comando al quale gli verrà inviato dell'output come pipe e se
MODO è '-|'
, il nome del file verrà interpretato come un comando che
invierà il suo output a noi. Nel caso della versione a 2 argomenti (e 1 argomento), si
dovrebbe sostituire il trattino ('-'
) con il comando.
Consultate Using open() for IPC in the perlipc manpage [``Usare open()
per IPC'', NdT]
per altri esempi su questo caso. (Non è ammesso l'uso di open
per eseguire un
comando e accedervi in scrittura e in lettura, consultate the IPC::Open2 manpage,
the IPC::Open3 manpage e Bidirectional Communication in the perlipc manpage
[``Comunicazioni bidirezionali'', NdT] per delle alternative).
Nel caso della versione a tre o più argomenti della apertura delle pipe, se
LIST è specificato (ulteriore parametro dopo il nome comando) allora
LIST diventa la lista dei parametri da inviare al comando quando invocato, se la
piattaforma in uso lo permette. Il significato di open
con più di tre
argomenti per chiamate diverse dalle pipe non è specificato.
Alcuni ``layers'' sperimentali potrebbero fornire parametri ulteriori per
dare significato a LIST.
Nel caso della versione a 2 argomenti (e 1 argomento), l'apertura di '-'
significa la lettura di STDIN mentre '>-'
l'apertura di STDOUT.
Potete usare i tre parametri per aprire specifici ``strati'' di IO (altrimenti noti come ``disciplines'' [letteralmente ``ordini, discipline'', NdT]) che verranno applicati all'handle, i quali modificano il funzionamento di come input e output vengono processatti (consultate the open manpage e the PerlIO manpage per ulteriori dettagli). Per esempio
open(FH, "<:utf8", "file")
aprirà il file codificato UTF-8 contenente caratteri Unicode,
si veda the perluniintro manpage. Va notato che se lo strato è specificato
nel caso di tre parametri, gli strati impostati di default dalla direttiva
open
vengono ignorati.
Open restituisce un valore diverso da zero in caso di successo, il valore
indefinito diversamente. Se la open
presenta una pipe, il valore restituito
può essere il PID del processo figlio.
Se si esegue Perl su un sistema che distingue fra file di testo e file binari,
controllate binmode per alcuni consigli su come gestire questi casi. La
chiave di distinzione fra sistemi che richiedono binmode
e quelli che non
lo richiedono è il loro formato di file di testo. Sistemi come Unix,
Mac OS e Plan 9, che delimitano le linee con un singolo carattere, codificato
in C come "\n"
, non richiedono binmode
. Gli altri lo richiedono.
Quando si apre un file, non è buona norma continuare la normale
esecuzione se la chiamata fallisce, per questa ragione open
viene
frequentemente usata con die
. Anche se die
non farà quanto
voluto (nel caso di script CGI, dove vorreste ottenere una pagina di
errore formattata (ma ci sono dei moduli che possono aiutare con questo
problema)) dovreste sempre controllare il valore restituito dalla apertura
di un file. Fa eccezione il raro caso quando si intende usare un filehandle
NON aperto.
Un caso speciale, la versione a 3 argomenti in modalità
lettura/scrittura dove il terzo parametro sia undef
:
open(TMP, "+>", undef) or die ...
che apre un filehandle su un file temporaneo anonimo. Inoltre, l'utilizzo di
``+<'' funziona per simmetria ma dovreste realmente considerare di scrivere prima
qualcosa sul file temporaneo. Avrete la necessitè di utilizzare seek()
per effettuare la lettura.
A partire dalla version 5.8.0, il perl è stato compilato usando PerlIO di default. A meno che voi non abbiate cambiato questo aspetto (cioè Configure -Uuseperlio), potete aprire i filehandle in file ``in memoria'' mantenuti entro scalari Perl tramite:
open($fh, '>', \$variabile) || ..
Tuttavia, se volete riaprire STDOUT
oppure STDERR
come file
``in memoria'', prima dovete chiuderli:
close STDOUT; open STDOUT, '>', \$variabile or die "Impossibile aprire STDOUT: $!";
Esempio:
$ARTICOLO = 100; open ARTICOLO or die "Impossibile trovare l'articolo $ARTICOLO: $!\n"; while (<ARTICOLO>) {...
open(LOG, '>>/usr/spool/news/twitlog'); # (log e` riservato) # se la open fallisce, l'output viene perso
open(DBASE, '+<', 'dbase.mine') # aperto per aggiornare or die "Impossibile aprire 'dbase.mine' per aggiornare: $!";
open(DBASE, '+<dbase.mine') # piu` rapidamente or die "Impossibile aprire 'dbase.mine' per aggiornare: $!";
open(ARTICLE, '-|', "caesar <$article") # decodifica articolo or die "Impossibile avviare caesar: $!";
open(ARTICLE, "caesar <$article |") # piu` rapidamente or die "Impossibile avviare caesar: $!";
open(EXTRACT, "|sort >Tmp$$") # $$ e` il pid del nostro processo or die "Impossibile avviare sort: $!";
# in memory files open(MEMORY,'>', \$var) or die "Impossibile aprire il file in memoria: $!"; print MEMORY "pippo!\n"; # l'output andra` a finire in $var
# processa la lista degli argomenti dei file insieme con ogni include
foreach $file (@ARGV) { process($file, 'fh00'); }
sub process { my($nomefile, $input) = @_; $input++; # questo e` un incremento di stringa unless (open($input, $nomefile)) { print STDERR "Impossibile aprire $nomefile: $!\n"; return; }
local $_; while (<$input>) { # si noti l'uso di indirezione if (/^#include "(.*)"/) { process($1, $input); next; } #... # qualunque cosa } }
Consultate the perliol manpage per informazioni dettagliate su PerlIO.
Inoltre potete, nella tradizione della Bourne shell, specificare un EXPR
che inizia con '>&'
, nel qual caso il resto della stringa viene
interpretato come un filehandle (o descrittore di file, se è numerico)
per essere duplicato (come dup(2)) e aperto. Potete usare &
dopo >
, >>
,
<
, +>
, +>>
e +<
. La modalità che
specificate deve essere uguale alla modalità del filehandle originale.
(Duplicare un filehandle non entra nel merito dell'esistenza di precedenti buffer
di IO). Se usate la versione a 3 argomenti, potete passare un numero, il nome di
un filehandle oppure un normale ``riferimento ad un glob''.
Ecco uno script che salva, redirige e ripristina STDOUT
e STDERR
usando
diversi metodi:
#!/usr/bin/perl open my $vecchioout, ">&STDOUT" or die "Impossibile duplicare STDOUT: $!"; open VECCHIOERR, ">&", \*STDERR or die "Impossibile duplicare STDERR: $!";
open STDOUT, '>', "pippo.out" or die "Impossibile redirezionare STDOUT: $!"; open STDERR, ">&STDOUT" or die "Impossibile duplicare STDOUT: $!";
select STDERR; $| = 1; # rendiamolo non bufferizzato select STDOUT; $| = 1; # rendiamolo non bufferizzato
print STDOUT "stdout 1\n"; # questo funziona print STDERR "stderr 1\n"; # anche per sottoprocessi
open STDOUT, ">&", $vecchioout or die "Impossibile duplicare \$vecchioout: $!"; open STDERR, ">&VECCHIOERR" or die "Impossibile duplicare VECCHIOERR: $!";
print STDOUT "stdout 2\n"; print STDERR "stderr 2\n";
Se specificate '<&=X'
, dove X
è un numero descrittore di file,
oppure un filehandle, allora Perl eseguirà l'equivalente della funzione C
fdopen
su quel descrittore di file (e non chiamerà dup(2)); questo
è un modo d'uso più parsimonioso dei descrittori di file.
Per esempio:
# apertura in input, riutilizzando il fileno di $fd open(FILEHANDLE, "<&=$df")
oppure
open(FILEHANDLE, "<&=", $df)
oppure
# apertura in aggiornamento, utilizzando il fileno di VECCHIOFH open(FH, ">>&=", VECCHIOFH)
oppure
open(FH, ">>&=VECCHIOFH")
Essere parsimoniosi sui filehandle è utile anche (al di
là dell'essere parsimoniosi) per esempio quando qualcosa
è dipendente dai descrittori dei file, come per esempio
l'uso di lock tramite flock(). Se utilizzate semplicemente
open(A, '>>&B')
, il filehandle A non avrà lo stesso
descrittore di file che ha B e quindi flock(A)
non farà
un flock(B)
e viceversa. Ma con open(A, '>>&=B')
il
filehandle condividerà lo stesso descrittore di file.
Va notato che se state usando un Perl più vecchio della
5.8.0., Perl userà la fdopen()
della libreria C standard
per implementare la funzionalità ``=''. Su molti sistemi
Unix, fdopen()
fallisce quando dei descrittori di file eccedono un
certo valore, tipicamente 255. Per le versioni di Perl 5.8.0 e
precedenti, PerlIO è molto spesso la norma.
Potete vedere se il Perl è stato compilato con PerlIO eseguendo
perl -V
e cercando la linea userperlio=
. Se useperlio
è
define
, avete PerlIO, altrimenti no.
Se aprite una pipe col comando '-'
, cioè sia con '|-'
o
'-|'
con la versione a 2 argomenti (o 1) di open(), allora viene eseguita
una fork implicita e restituito il pid del processo figlio per il processo
padre, 0
al processo figlio. (Usate defined($pid)
per determinare
se la open ha avuto successo). Il filehandle si riconduce di norma al
padre, ma l'input/output su quel filehandle viene passato attraverso
pipe da/per lo STDOUT/STDIN del processo figlio. Nel processo figlio il
filehandle non è aperto, l'input/output avviene dal/al nuovo STDIN
o STDOUT. Solitamente questo viene usato come il normale open con pipe quando
volete esercitare maggior controllo proprio su come viene eseguito il comando
pipe, come quando state eseguendo setuid e non si vuole controllare il comando
shell per i metacaratteri. Le seguenti triple sono più o meno
equivalenti:
open(PIPPO, "|tr '[a-z]' '[A-Z]'"); open(PIPPO, '|-', "tr '[a-z]' '[A-Z]'"); open(PIPPO, '|-') || exec 'tr', '[a-z]', '[A-Z]'; open(PIPPO, '|-', "tr", '[a-z]', '[A-Z]');
open(PIPPO, "cat -n '$file'|"); open(PIPPO, '-|', "cat -n '$file'"); open(PIPPO, '-|') || exec 'cat', '-n', $file; open(PIPPO, '-|', "cat", '-n', $file);
Nell'ultimo esempio, in ogni blocco di codice viene mostrata la pipe come
``list form'' [un elenco di parametri, NdT], non supportato da alcuna
piattaforma. Una buona regola è: se il vostro sistema operativo
ha una vera fork()
(in altre parole, se è UNIX) putete usare la
list form.
Consultate Safe Pipe Opens in the perlipc manpage [``Apertura sicura di pipe'', NdT] per ulteriori esempi.
A partire dalla versione 5.6.0, Perl tenta di svuotare i buffer, tutti i file
aperti in output prima di qualsiasi operazione che potrebbe effettuare il fork,
ma questo potrebbe non essere supportato su qualche piattaforma (si veda
the perlport manpage). Per essere sicuri, dovreste impostare $|
($AUTOFLUSH nel modulo
English) oppure chiamare il metodo autoflush()
di IO::Handle
su ogni handle
aperto.
Su sistemi che supportano i flag close-on-exec [``chiuso-su-esecuzione'', NdT], il flag sarà impostato per ogni nuovo descrittore di file aperto, come determinato dal valore di $^F. Si veda $^F in the perlvar manpage.
Chiudere uno qualsiasi dei filehandle di pipe provoca l'attesa del processo
padre che il processo figlio finisca, restituendo lo stato in $?
.
Il nome del file passato nella chiamata alla open()
nella versione con 2 argomenti
(o 1) avrà gli spazi in testa e coda eliminati, e i normali caratteri
di redirezione verranno onorati. Questa proprietà, nota come
``magic open'' [``apertura magica'', NdT], può spesso essere usata con
buoni esiti. Un utente potrebbe specificare un nomefile tipo
``rsh cat file |'', oppure voi potreste cambiare alcuni particolari nomifle
in base alle necessità:
$nomefile =~ s/(.*\.gz)\s*$/gzip -dc < $1|/; open(FH, $nomefile) or die "Impossibile aprire $nomefile: $!";
Usate la versione della open a 3 argomenti per aprire un file che contiene strani caratteri arbitrari,
open(PIPPO, '<', $file);
oppure potrebbe essere necessario proteggere un qualsiasi spazio a inizio o fine nome:
$file =~ s#^(\s)#./$1#; open(PIPPO, "< $file\0");
(questo potrebbe non funzionare su qualche bizzarro filesystem). Uno potrebbe scegliere, in coscienza, fra la versione magica e la versione a tre argomenti di open():
open IN, $ARGV[0];
permette all'utente di specificare un parametro della forma "rsh cat file |"
,
ma non funziona su un nome file con uno spazio, mentre
open IN, '<', $ARGV[0];
ha esattamente le restrizioni opposte.
Se volete una ``vera'' open
in stile C (consultate open(2) sul vostro sistema),
dovrete usare la funzione sysopen
, la quale non implica questo genere di ``magia''
(ma potrebbe usare alcuni differenti filemode rispetto alla open()
del Perl, i
quali sono mappati alla fopen()
del C). Questa è un'altra possibilita per
proteggere meglio il vostro nome file dalle interpretazioni.
Per esempio:
use IO::Handle; sysopen(HANDLE, $path, O_RDWR|O_CREAT|O_EXCL) or die "sysopen $path: $!"; $vecchiofh = select(HANDLE); $| = 1; select($vecchiofh); print HANDLE "Delle cose $$\n"; seek(HANDLE, 0, 0); print "Il file contiene: ", <HANDLE>;
Usando il costruttore dal package IO::Handle
(oppure una delle delle sue
sottoclassi, tipo IO::File
oppure IO::Socket
), potete generare filehandle
anonimi che hanno come scope lo stesso di una qualsiasi variabile che possa
contenere riferimenti, e automaticamente chiusi comunque, ogniqualvolta uscite
da tale scope:
use IO::File; #... sub leggo_miofile_munged { my $TUTTO = shift; my $handle = new IO::File; open($handle, "miofile") or die "miofile: $!"; $primo = <$handle> or return (); # Qui viene chiuso autimaticamente. mung $primo or die "mung fallito"; # Oppure qui. return $primo, <$handle> if $TUTTO; # Oppure qui. $primo; # Oppure qui. }
Consultate seek per qualche dettaglio riguardo la possibilità di mescolare letture e scritture.
readdir
,
telldir
, seekdir
, rewinddir
e closedir
. Restituisce vero se l'operazione ha avuto successo.
I DIRHANDLE hanno il loro spazio dei nomi separato da quello dei FILEHANDLE.
$_
.
Per il contrario, si veda chr. Consultate the perlunicode manpage e the encoding manpage per ulteriori informazioni su Unicode.
our
associa un nome elementare con una variabile di package nel corrente
package per usarla all'itenro dello scope corrente. Quando è in
vigore use strict 'vars'
, our
vi permette di dichiarare variabili globali
senza qualificarle con i nomi dei package, all'interno dello scope lessicale
della dichiarazione our
. Così our
differisce da ``use vars'',
il cui scope è a livello di package
A differenza di my
, che alloca sia dello spazio per una variabile sia
associa un nome elementare con quello spazio per un suo uso all'interno dello
scope corrente, our
associa un nome elementare con una variabile di package
nel package corrente, per un suo uso all'interno dello scope corrente. In altre
parole, our
ha le stesse regole di scope di my
, ma non crea necessariamente
una variabile.
Se è indicato più di un valore, la lista deve essere inclusa tra parentesi.
our $pippo; our($pluto, $paperino);
Un dichiarazione our
dichiara una variabile globale che sarà
visibile su tutto il suo scope lessicale, persino attraverso i limiti
di un package. Il package in cui la variabile viene inserita è
determinato al momento della dichiarazione, non al momento dell'uso.
Ciò significa che è valido il seguente comportamento:
package Pippo; our $pluto; # dichiara $Pippo::pluto per il resto dello scope lessicale $pluto = 20;
package Pluto; print $pluto; # stampa 20, visto che si riferisce a $Pippo::pluto
Sono permesse multiple dichiarazioni our
con lo stesso nome all'interno dello stesso
scope lessicale, se si trovano all'interno di differenti package. Se si trovano nello
stesso package, Perl genererà degli avvertimenti solo se li avete richiesti,
proprio come delle multiple dichiarazioni di my
. Diversamente da una seconda
dichiarazione my
, che legherà il nome ad una nuova variabile, una seconda
dichiarazione our
nello stesso package, nello stesso scope, è
solamente ridondante.
use warnings; package Pippo; our $pluto; # dichiara $Pippo::pluto per il resto dello scope lessicale $pluto = 20;
package Pluto; our $pluto = 30; # dichiara $Pluto::pluto per il resto dello scope lessicale print $pluto; # stampa 30
our $pluto; # genera un warning ma non ha altri effetti print $pluto; # stampa ancora 30
Una dichiarazione our
può anche avere una lista di
attributi associata ad essa.
Le semantiche esatte e l'interfaccia di TIPO ed ATTRIBUTI sono ancora
in evoluzione. TIPO è al momento legato all'uso della direttiva
fields
, a gli attributi sono gestiti utilizzando la direttiva
attributes
o, a partire da Perl 5.8.0, anche tramite il modulo
Attribute::Handlers
. Consultate Private Variables via my() in the perlsub manpage
[``Variabili private tramite my()'', NdT] per i dettagli e the fields manpage,
the attributes manpage e the Attribute::Handlers manpage.
Il solo attributo per our()
attualmente riconosciuto è
unique
, che indica che una singola copia del globale deve essere
utilizzata da tutti gli interpreti nel caso il programma stia girando
in un ambiente multi-interprete. (Il comportamento predefinito prevede
che ogni interprete abbia la sua copia del globale). Esempi:
our @EXPORT : unique = qw(pippo); our %EXPORT_TAGS : unique = (pluto => [qw(aa bb cc)]); our $VERSION : unique = "1.00";
Va notato che questo attributo ha anche l'effetto di far sì che il globale diventi in sola lettura quando il primo nuovo interprete viene clonato (per esempio, quando viene creato il primo nuovo thread).
Gli ambienti multi interprete possono esistere tramite l'emulazione di
fork()
sotto Windows, o incapsulando perl in un'applicazione
multi-threaded. L'attributo unique
non fa nulla in tutti gli altri
ambienti.
Attenzione: l'attuale implementazione di questo attributo opera sui typeglob
associati con la variabile; questo significa che our $x : unique
ha anche l'effetto
di our @x : unique; our %x : unique
. Questo potrebbe essere soggetto a cambiamenti.
Il TEMPLATE è una sequenza di caratteri che forniscono l'ordine ed il tipo dei valori, come indicato di seguito:
a Una stringa con dati binari arbitrari, sara` completata da null. A Una stringa tesuale (ASCII), sara` completata da spazi. Z Una stringa terminata da null (ASCIZ), sara` completata da null. b Una stringa di bit (ordine ascendente dei bit all'interno di ciascun bye, come vec()). B Una stringa di bit (ordine discendente dei bit all'interno di ciascun bye). h Una stringa esadecimale (nybble basso per primo). H Una stringa esadecimale (nybble alto per primo).
c Un carattere con segno. C Un carattere senza segno. Supporta solo i byte. Per l'Unicode, si veda U.
s Un intero short con segno. S Un intero short senza segno. (Questo 'short' ['corto', NdT] e` _esattamente_ di 16 bit, il che puo` differire da cio` che un compilatore C locale chiama 'short'. Se desiderate degli interi corti della lunghezza nativa, utilizzate il suffisso '!').
i Un intero con segno. I Un intero senza segno. (Questo 'intero' e` di _almeno_ 32 bit. La sua esatta dimensione dipende da cio` che un compilatore C locale chiama 'int', e potrebbe persino essere piu` grande del 'long' descritto di seguito).
l Un intero long con segno. L Un intero long senza segno. (Questo 'long' ['lungo', NdT] e` _esattamente_ di 32 bit, il che puo` differire da cio` che un compilatore C locale chiama 'long'. Se desiderate degli interi lunghi della lunghezza nativa, utilizzate il suffisso '!').
n Un intero short senza segno in ordine di "rete" (big-endian). N Un intero long senza segno in ordine di "rete" (big-endian). v Un intero short senza segno in ordine "VAX" (little-endian). V Un intero long senza segno in ordine "VAX" (little-endian). (Questi 'short' e 'long' sono _esattamente_ di 16 bit ed _esattamente_ di 32 bit, rispettivamente).
q Un quad con segnp (64-bit). Q Un quad senza segno. (I quad sono disponibili solo se il vostro sistema supporta gli interi a 64 bit, _e_ se Perl e` stato compilato per supportarli. In caso contario verra` generato un errore bloccante).
j Un intero con sengo (un intero di Perl, IV). J Un intero senza segno (un intero senza segno di Perl, UV).
f Un numero in virgola mobile in singola precisione, in formato nativo. d Un numero in virgola mobile in doppia precisione, in formato nativo.
F Un numero in virgola mobile nel formato nativo nativo (un numero in virgola mobile interno di Perl, NV).
D Un numero in virgola mobile long in doppia precisione, in formato nativo. (I numeri in doppia precisione long sono disponibili solo se il vostro sistema supporta i numeri lunghi in doppia precisione, _e_ se Perl e` stato compilato per supportarli. In caso contario verra` generato un errore bloccante).
p Un puntatore ad una stringa terminata da null. P Un puntatore ad una struttura (stringa a lunghezza fissa).
u Una stringa uuencoded. U Un numero di carattere Unicode. Internamente, e` codificato in UTF-8. (o UTF-EBCDIC su sistemi EBCDIC).
w Un intero compresso BER (non un BER ASN.1, si consulti perlpacktut per dettagli). I suoi byte rappresentano un intero senza segno in base 128, con la cifra piu` significativa per prima, e con il minore numero di cifre possibile. L'ottavo bit (il bit alto) viene impostato su ciascun byte, tranne l'ultimo.
x Un byte null. X Effettua il backup di un byte. @ Riempie con null fino ad una posizione assoluta. ( Inizia un gruppo ().
Valgono le seguenti regole:
a
, A
,
Z
, b
, B
, h
, H
, @
, x
, X
e P
, la funziona pack
preleverà quel numero di valori da LISTA. Un *
come numero di
ripetizioni indica di usare tutti gli elementi rimasti, tranne che per
@
, x
, X
, dove equivale a 0
, e u
, dove equivale a 1 (o 45,
che è lo stesso). Il numero di ripetizioni può essere
racchiuso tra parentesi quadre, come in pack 'C[80]', @arr
.
È possibile sostituire il numero di ripetizioni con un template,
racchiuso tra parentesi quadre; a questo punto, la lunghezza in byte di
questo template viene utilizzata come conteggio delle ripetizioni. Per
esempio, x[L]
salta un intero long (salta cioè il numero di
byte in un intero); il template $t X[$t] $t
scompatta [con unpack()), NdT]
il doppio di quanto compatti $t. Se il template tra parentesi contiene dei
comandi di allineamento (come ad esempio x![d]
), la lunghezza
compattata viene calcolata come se l'inizio del template avesse
l'allineamento massimo possibile.
Quando viene utilizzato con Z
, *
provoca l'aggiunta di un byte
null alla fine (cosicché il risultato compattato sia di
un'unità più lungo del byte length
dell'elemento).
Il numero di ripetizioni per u
viene interpretato come il numero
massimo di byte da codificare per ciascuna linea di output, con 0 ed 1
sostituiti da 45.
a
, A
, and Z
prelevano solamente un valore, ma lo
compattano come una stringa della lunghezza specificata, completando
con null o spazi se necessario. Al momento di scompattare, A
rimuove eventuali spazi e null all'inizio, Z
rimuove tutto dopo il
primo null, e a
restituisce i dati così come sono. Per
compattare, a
e Z
sono equivalenti.
Se il valore-da-compattare è troppo lungo, esso viene troncato.
Se è troppo lungo e viene fornito esplicitamente un conteggio,
Z
compatta solo $conteggio-1
byte, seguiti da un null. Dunque,
Z
compatta sempre un null al termine della stringa, in qualsiasi
circostanza.
b
e B
compattano una stringa lunga il
numero di bit specificato. Ciascun byte dell'input di pack()
genera un
bit del risultato. Ogni bit del risultato è basato sul bit meno
significativo del byte di input corrispondente, cioè con
ord($byte)%2
. In particolare i byte "0"
e "1"
generato i bit
0 e 1, e così fanno i byte "\0"
e "\1"
.
A partire dall'inizio della stringa in input a pack(), ciascun gruppo
di 8 byte viene convertito in 1 byte di output. Con il formato b
, il
primo byte del gruppo di 8 determina il bit meno significativo di un
byte, mentre con il formato B
determina quello più
significativo.
Se la lunghezza della stringa in input non è divisibile
esattamente per 8, la parte rimanente viene compattata come se la
stringa in input fosse completata di byte null alla fine.
In maniera analoga, al momento di utilizzare unpack()
i bit ``extra''
vengono ingorati.
Se la stringa in input a pack()
è più lunga di
quanto necessario, i byte in più vengono ignorati. Un *
come conteggio delle ripetizioni di pack()
indica di utilizzare
tutti i byte dell'input. Al momento di utilizzare unpack()
i bit
sono convertiti in una stringa di "0"
e "1"
.
h
e H
compattano una stringa lunga il numero di
nybble (gruppi di 4 bit, rappresentati come cifre esadecimali,
0-9a-f) specificato.
Ciascun byte in input a pack()
genera 4 bit del risultato. Per i
byte non alfabetici, il risultato è basato sui 4 bit meno
significativi del byte in input, cioè come in ord($byte)%16
.
In particolare, i byte "0"
e "1"
generano nybble 0 e 1,
così come i byte "\0"
e "\1"
. Per i byte "a".."f"
e "A".."F"
il risultato è compatibile con le solite cifre
esadecimali, dunque "a"
e "A"
generano entrambi il nybble
0xa==10
. Il risultato per i byte "g".."z"
e "G".."Z"
non
è ben definito.
A partire dall'inizio della stringa in input a pack(), ciascuna
coppia di byte viene convertita in 1 byte dell'output. Con il
formato h
il primo byte della coppia determina il nybble meno
significativo del byte il output, e con il formato H
esso ne
determina il nybble più significativo.
Se la lunghezza della stringa in input non è pari, allora
essa viene completata con un byte null alla fine. In maniera
analoga, al momento dell'utilizzo di unpack()
i nybble ``extra''
vengono ignorati.
Se la stringa in input a pack()
è più lunga del
necessario, i byte in più vengono ignorati. Un *
come
conteggio delle ripetizioni di pack()
indica di utilizzare tutti i
byte dell'input. Al momento di utilizzare unpack()
i bit sono
convertiti in una stringa di cifre esadecimali.
p
compatta un puntatore ad una stringa terminata da
null. Siete responsabile dell'assicurarvi che la stringa non sia
un valore temporaneo (che può potenzialmente essere
deallocato prima che utilizziate il risultato compattato). Il tipo
P
compatta un puntatore ad una struttura della dimensione
indicata dalla lunghezza. Viene creato un puntatore a NULL che il
corrispondentente valore per p
o P
è undef
.
Un comportamento simile si ha con unpack().
Il template /
permette di compattare e scompattare
stringhe in cui la struttura compattata contiene un conteggio di
byte seguito dalla stringa stessa. Dovete scrivere
lunghezza-elemento/
stringa-elemento.
La lunghezza-elemento può essere qualsiasi lettera di
template di pack
, e descrive come è compattato il valore
di lunghezza. Quelle di utilizzo più frequente sono quelle di
compattamento degli interi, quali n
(per stringhe Java), c<w>
(per ASN.1 o SNMP) e N
(per Sun, XDR).
Per pack
, la stringa-elemento deve, al momento, essere "A*"
, "a*"
oppure "Z*"
. Con unpack
la lunghezza della stringa è
ottenuta da lunghezza-elemento, ma se inserite il carattere '*'
viene ingorata. Per tutti gli altri codici, unpack
applica il valore della
lunghezza all'elemento successivo, che non deve avere un conteggio delle ripetizioni.
unpack 'C/a', "\04Gurusamy"; restituisce 'Guru' unpack 'a3/A* A*', '007 Bond J '; restituisce (' Bond','J') pack 'n/a* w/a*','hello,','world'; restituisce "\000\006hello,\005world" [ciao mondo, NdT]
La lunghezza-elemento non viene restituita esplicitamente da
unpack
.
L'aggiunta di un conteggio a lunghezza-elemento non è
probabilmente di alcuna utilità, a meno che la lettera non
sia A
, a
o Z
. Compattare con una lunghezza-elemento di
a
o Z
può causare l'inserimento di catteri "\000"
,
che Perl non considera legali all'interno delle stringhe numeriche.
s
, S
, l
e L
possono essere immediatamente
seguiti da un suffisso !
, che indica che essi sono short o long
nativi, come potete vedere sopra, ad esempio un l
solitario indica
esattamente 32 bit, mentre il long
nativo (come è
considerato dal compilatore C locale) può essere più
grande. Questo è un problema soprattutto nei sistemi a 64-bit.
Potete controllare se l'utilizzo di !
crea qualche differenza in
questa maniera
print length(pack("s")), " ", length(pack("s!")), "\n"; print length(pack("l")), " ", length(pack("l!")), "\n";
Anche i!
e I!
funzionano, ma solo per questioni di completezza;
essi sono identici a i
and I
.
Le reali dimensioni (in byte) degli short, int, long e long long nativi sui sistemi dove Perl è stato compilato sono disponibili anche tramite the Config manpage:
use Config; print $Config{shortsize}, "\n"; print $Config{intsize}, "\n"; print $Config{longsize}, "\n"; print $Config{longlongsize}, "\n";
($Config{longlongsize}
risulterà non definito se il
vostro sistema non supporta i long lon).
s
, S
, i
, I
, l
, L
, j
e J
sono intrinsecamente non portabili tra diversi processori e sistemi
operativi, poiché essi obbediscono all'ordine dei byte ed
al tipo di endian locali. Per esempio, un intero di 4 byte 0x12345678
(305419896 in decimale) viene ordinato nativamente (ordinato e gestito
dai registri della CPU) in byte come:
0x12 0x34 0x56 0x78 # big-endian 0x78 0x56 0x34 0x12 # little-endian
Fondamentalmente, le CPU Intel e VAX sono little-endian, mentre tutti gli altri, ad esempio Motorola m68k/88k, PPC, Sparc, HP PA, Power, e Cray, sono big-endian. Alpha e MIPS possono essere entrambi: Digital/Compaq li usava/usa in modalità little-endian; SGI/Cray li usa in modalità big-endian.
I nomi 'big-endian' e 'little-endian' sono riferimenti fumettistici al classico ``Gulliver's Travels'' [``I viaggi di Gulliver'', NdT] (attraverso il foglio ``On Holy Wars and a Plea for Peace'' di Danny Cohen, USC/ISI IEN 137, April 1, 1980) [``Sulle guerre sante ed un appello per la pace'', NdT] e le abitudini dei Lillipuziani per quanto riguarda il mangiare le uova.
Alcuni sistemi possono avere un ordine dei byte più strano, come:
0x56 0x78 0x12 0x34 0x34 0x12 0x78 0x56
Potete conoscere la preferenza del vostro sistema con:
print join(" ", map { sprintf "%#02x", $_ } unpack("C*",pack("L",0x12345678))), "\n";
L'ordine dei byte sul sistema dove Perl è stato compilato è inoltre disponibile tramite the Config manpage:
use Config; print $Config{byteorder}, "\n";
I byteorder '1234'
e '12345678'
sono little-endian, '4321'
e '87654321'
sono big-endian.
Se desiderate degli interi compattati portabili, utilizzati i formati
n
, N
, v
, e V
: la loro dimensione e tipo di endian sono
conosciuti. Consultate anche the perlport manpage.
Va notato che Perl usa i double internamente per tutti i calcoli numerici,
e la conversione da double a float e viceversa causa una perdita di
precisione (ad esempio, unpack("f", pack("f", $pippo)
) non è
generalmente equivalente a $pippo).
U
, la stringa risultante verrà trattata
come codificata in Unicode. Potete forzare la codifica UTF8 su una stringa
inserendo un U0
iniziale, ed i byte che seguono saranno interpretati
come caratteri Unicode. Se non volete che ciò accada, potete far
iniziare il vostro schema con C0
(o qualsiasi altra cosa) per forzare
Perl a non codificare in UTF8 la vostra stringa, facendo poi seguire a
ciò un U*
da qualche parte nel vostro schema.
Dovete occuparvi voi di eventuali allineamenti o completamenti, inserendo
ad esempio sufficienti 'x'
quando state compattando. Non c'è
alcun modo in cui pack()
ed unpack()
possono sapere dove vanno o da dove
vengono i byte. Quindi, pack
(e unpack
) gestisce il suo output ed
input come fossero delle pure sequenze di byte.
Un gruppo () è un sotto-TEMPLATE racchiuso tra parentesi. Un gruppo
può avere un conteggio di ripetizioni, sia alla fine che tramite il
template di caratteri /
. All'interno di ogni ripetizione di un gruppo,
il posizionamento tramite @
fa ripartire di nuovo da 0. Quindi, il
risultato di
pack( '@1A((@2A)@3A)', 'a', 'b', 'c' )
è la stringa ``\0a\0\0bc''.
x
ed X
accettano il modificatore !
. In questo caso si comportano
come comandi di allineamento; saltano avanti e indietro alla posizione
allineata più vicina ad un multiplo di un numero di byte pari a
conteggio
. Per esempio, per utilizzare pack()
o unpack()
su una
struct {char c; double d; char cc[2]}
del C, potreste dover utilizzare
il template C x![d] d C[2]
; questo assume che i double siano allineati
alla dimensione dei double.
Per i comandi di allineamento, un conteggio
di 0 equivale ad un
conteggio
di 1; entrambi non risultano in alcuna operazione.
#
e termina con la fine della
linea. Per separate i codici compattati gli uni dagli altri, possono
essere utilizzati degli spazi, ma deve seguire immediatamente un
modificatore !
ed un numero di ripetizioni.
Se TEMPLATE richiede più argomenti per pack()
di quanti ne siano
stati in realtà forniti, pack()
assume un numero addizionale di
argomenti ""
. Se TEMPLATE richiede meno argomenti per pack()
di quanti
ne siano stati in realtà forniti, gli argomenti in più
vengono ignorati.
Esempi:
$pippo = pack("CCCC",65,66,67,68); # pippo eq "ABCD" $pippo = pack("C4",65,66,67,68); # stessa cosa $pippo = pack("U4",0x24b6,0x24b7,0x24b8,0x24b9); # stessa cosa con le lettere cerchiate Unicode
$pippo = pack("ccxxcc",65,66,67,68); # pippo eq "AB\0\0CD"
# nota: gli esempi qui sopra che utilizzano "C" e "c" sono validi # solo su sistemi ASCII o derivati come ISO Latin 1 e UTF-8. # In EBCDIC il primo esempio diventerebbe # $pippo = pack("CCCC",193,194,195,196);
$pippo = pack("s2",1,2); # "\1\0\2\0" su little-endian # "\0\1\0\2" su big-endian
$pippo = pack("a4","abcd","x","y","z"); # "abcd"
$pippo = pack("aaaa","abcd","x","y","z"); # "axyz"
$pippo = pack("a14","abcdefg"); # "abcdefg\0\0\0\0\0\0\0"
$pippo = pack("i9pl", gmtime); # un vera struct tm (almeno, sul mio sistema)
$utmp_template = "Z8 Z8 Z16 L"; $utmp = pack($utmp_template, @utmp1); # una struct utmp (in stile BSD)
@utmp2 = unpack($utmp_template, $utmp); # "@utmp1" eq "@utmp2"
sub bintodec { unpack("N", pack("B32", substr("0" x 32 . shift, -32))); }
$pippo = pack('sx2l', 12, 34); # short 12, completamento con due zeri, long 34 $pluto = pack('s@4l', 12, 34); # short 12, riempito con zeri fino alla posizione 4, long 34 # $pippo eq $pluto
Lo stesso template può in genere venire usato anche in unpack().
my
). Tutti gli identificatori dinamici non
esplicitamente qualificati apparterrano a questo spazio dei
nomi. Un'istruzione che dichiara un package influisce solo
sulle variabili dinamiche, incluse quelle dichiarate con
local
, ma non su quelle lessicali, cioè create
con my
. Tipicamente, package
dovrebbe essere la prima
dichiarazione in un file che viene incluso con l'operatore
require
o user
. Potete passare ad un package in più
di un punto; tale dichiarazione determina semplicemente quale
tabella dei simboli viene usata dal compilatore per la fine del
blocco in cui ci trova. Potete far riferimento a variabili e
filehandle in altri package prefissandoli con il nome del
package ed un doppio simbolo di due punti: $Package::Variable
.
Se il nome del package è vuoto, viene considerato il
package main
. Dunque, $::sail
equivale a $main::sail
(ed anche a $main'sail
, sintassi che ancora si vede in certo
codice vecchio).
Se SPAZIONOMI viene omesso, allora non viene dichiarato alcun package corrente, e tutti gli identificatori devono essere pienamente qualificati, oppure essere lessicali. Comunque, è fortemente sconsigliato non dichiarare uno spazio dei nomi. Ciò potrebbe infatti causare un comportamento inaspettato del vostro programma, o persino un crash in alcune versioni di Perl. La forma senza SPAZIONOMI è considerata obsoleta, e verrà rimossa a partire da una versione a venire.
Consultate Packages in the perlmod manpage per maggiori informazioni sui package, sui moduli, e sulle classi. Consultate the perlsub manpage per ulteriori informazioni sullo scope.
$|
per svuotare il vostro
HANDLEDISCRITTURA dopo ogni comando, a seconda dell'applicazione.
Consultate the IPC::Open2 manpage, the IPC::Open3 manpage e Bidirectional Communication in the perlipc manpage [``Comunicazione Bidirezionale, NdT] per esempi di cose come queste.
Sui sistemi che supportano sui file un flag close-on-exec [chiudi-su-esecuzione, NdT], il flag sarà impostato per il descrittore di file appena aperto, come determinato dal valore di $^F. Si veda $^F in the perlvar manpage.
$ARRAY[$#ARRAY--]
Se non ci sono elementi nell'array, restituisce il valore
indefinito (per quanto, questo possa accadere anche in altri
casi). Se ARRAY viene omesso, rimuove l'ultimo elemento dall'array
@ARGV
nel corpo principale del programma, e dall'array @_
nelle subroutine, proprio come shift
.
m//g
ha trovato qualcosa (se la variabile
non è specificata, viene usata $_
). Va notato che 0 è
un valido scostamento del match. undef
indica che la posizione della
ricerca è stata reimpostata (di solito a causa del fallimento di un match ma può
anche essere perché non è stato ancora effettuato alcun match sullo scalare).
pos
accede direttamente alla locazione usata dal motore delle espressioni regolari per
immagazzinare lo scostamento, dunque fare un assegnamento a pos
cambierà lo
scostamento e influenzerà la \G
zero-width assertion [asserzione di ampiezza zero, NdT]
nelle espressioni regolari. Il match non reimposta lo scostamento a cusa di un m//gc
fallito,
il ritorno da pos
non cambierà nemmeno in questo caso. Consultate the perlre manpage e the perlop manpage.
+
o utilizziate le
parentesi attorno agli argomenti). Se FILEHANDLE viene omesso,
la stampa viene direzionata all'output standard (o all'ultimo
canale di output selezionato, consultate select). Se anche
LISTA viene omessa, stampa $_
al canale di output
correntemente selezionato. Per impostare il canale di output a
qualcosa di diverso da STDOUT, utilizzate l'operazione select.
Il valore corrente di $,
(se impostato) viene stampato come
separatore di ciascun elemento di LISTA. Il valore corrente di
$\
(se impostato) viene stampato dopo che l'intera LISTA
è stata stampata. Poiché print accetta una
LISTA, ogni cosa contenuta in tale LISTA viene valutata in
contesto di lista, ed ogni subroutine che chiamate si
ritroverà una o più d'una delle sue espressioni
valutate in contesto di lista. State anche attenti a non far
seguire una parentesi di apertura alla parola chiave print, a
meno che non desideriate terminare gli argomenti da stampare
con la corrispondente parentesi di chisura, inserite un +
o
mettere parentesi attorno a tutti gli argomenti.
Va notato che se tenete i FILEHANDLE in un array, o comunque usate delle espressioni più complesse di una semplice variabile scalare per accederli, dovete usare un blocco che restituisca il filehandle:
print { $files[$i] } "cose da stampare\n"; print { $OK ? STDOUT : STDERR } "cose da stampare\n";
print FILEHANDLE sprintf(FORMATO, LISTA)
, tranne
per il fatto che $\
(il separatore di record dell'output) non
viene aggiunto. Il primo argomento della lista viene interpretato
come il formato per printf
. Si veda sprintf
per una
spiegazione dell'argomento formato. Se use locale
è
stato attivato, il carattere utilizzato per il punto decimale nella
formattazione dei numeri reali è influenzato dal locale
LC_NUMERIC. Consultate the perllocale manpage.
Si raccomanda di stare attenti a non cadere nella trappola di usare
printf
quando un semplice print
andrebbe bene. L'istruzione
print
è più efficiente e meno soggetta ad errori.
undef
se la funzione non ha prototipo). FUNZIONE è un riferimento a,
oppure il nome di una funzione di cui volete recuperare il prototipo.
Se FUNZIONE è una stringa che inizia con CORE::
, quello che
resta viene considerato il nome di una funzione interna del Perl. Se
la funzione interna non può essere ridefinita (come qw//
)
o i suoi argomenti non possono essere espressi mediante un prototipo
(come system
) restituisce undef
dato che la funzione interna non
si comporta proprio come una funzione Perl. Altrimenti, viene restituita
la stringa che descrive il prototipo equivalente.
for $valore (LISTA) { $ARRAY[++$#ARRAY] = $valore; }
ma è più efficiente. Restituisce il numero di
elementi che sono nell'array dopo l'esecuzione della push
.
/[A-Za-z_0-9]/
saranno preceduti da un
backslash nella stringa restituita, indipendentemente da qualsiasi
impostazione del locale). Questa è la funzione interna che
implementa il \Q
all'interno delle stringhe delimitate da doppi
apici.
Se ESPR viene omesso, quotemeta()
usa $_
.
0
e minore del valore di ESPR. (ESPR dovrebbe
essere positivo). Se ESPR viene omesso, viene usato il
valore 1
. Attualmente una ESPR con valore 0
viene
trattata in maniera speciale, come se fosse 1
; questo
non è stato documentato prima di perl 5.8.0 ed è
soggetto a cambiamenti nelle prossime versioni di perl.
srand
viene chiamata automaticamente se non è già
stato fatto. Consultate anche srand
.
Applicate int()
al valore restituito da rand()
se volete
numeri interi casuali anziché numeri razionali casuali.
Per esempio,
int(rand(10))
restituisce un intero casuale tra 0
e 9
, estremi compresi.
(Nota: Se la vostra funzione rand continua a restituire numeri troppo grandi o troppo piccoli, allora la vostra versione di Perl è stata probabilmente compilata con un numero sbagliato di RANDBITS).
0
alla fine del file, o il valore indefinito
se si è verificato un errore (in quest'ultimo caso, viene anche impostata
$!
). La lunghezza di SCALARE sarà aumentata o diminuita in maniera che
l'ultimo carattere effettivamente letto sia l'ultimo carattere dello scalare dopo
la lettura.
Può essere indicato uno SCOSTAMENTO per posizionare i dati
letti in qualche altro posto in SCALARE piuttosto che all'inizio.
Un OFFSET negativo indica la posizione specificata da tanti caratteri
quanti quelli specificati, contando all'indietro a partire dalla fine
della stringa. Un OFFSET maggiore della lunghezza di SCALAR fa sì
che la stringa sia completata con dei byte "\0"
fino alla lunghezza
richiesta, prima che il risultato della read venga aggiunto in coda.
La chiamata è effettivamente implementata in termini di chiamata
a fread(), del Perl o del sistema operativo. Per una vera chiamata
di sistema read(2), si veda sysread
.
Notate i caratteri: a seconda dello stato del filehandle, possono
essere letti byte (8-bit) o caratteri. Di default tutti i filehandle operano
su byte, ma se ad esempio il filehandle è stato aperto con il layer di
I/O :utf8
(si veda open e la direttiva open
, the open manpage), le operazioni di
I/O opereranno su caratteri, non su byte. In maniera analoga per la direttiva
:encoding
: in quel caso può essere letto pressoché qualsiasi
carattere.
opendir
. Se usato in un contesto lista, restituisce tutti gli
elementi rimanenti nella directory. Se non si sono più
elementi, restituisce il valore indefinito in contesto scalare
oppure una lista nulla in contesto lista.
Se avete in mente di utilizzare i valori restituiti da readdir
per dei test su file, fareste meglio a prependere la directory in
questione. Altrimenti, visto che non viene cambiata la directory
corrente (chdir
) nella directory che si sta leggendo, potreste
stare effettuando il test sul file sbagliato.
opendir(DIR, $una_dir) || die "non posso aprire la dir $una_dir: $!"; @punti = grep { /^\./ && -f "$una_dir/$_" } readdir(DIR); closedir DIR;
$/
o
$INPUT_RECORD_SEPARATOR
[record separatore di input, NdT].
Si veda $/ in the perlvar manpage.
Quando $/
è stato impostato a undef
, e readline()
viene
chiamato in contesto scalare (ossia in slurp mode [modalità
slurp, NdT]) e se il file è vuoto, restituisce ''
la prima volta, e undef
le volte successive.
Questa è la funzione utilizzata internamente
dall'implementazione dell'operatore <ESPR>
, ma può
essere usata direttamente. L'operatore <ESPR>
viene discusso
in dettaglio in I/O Operators in the perlop manpage [``Operatori di I/O'', NdT].
$line = <STDIN>; $line = readline(*STDIN); # stessa cosa
Se readline incontra un errore del sistema operativo, $!
verrà
impostato con il messaggio d'errore corrispondente. Può essere
utile controllare $!
quando state leggendo dai filehandle di cui non
vi fidate, come tty, oppure un socket. Il seguente esempio usa
readline
in forma di operatore, e svolge i passi necessari ad
assicurarsi che readline
sia andato a buon fine.
for (;;) { undef $!; unless (defined( $linea = <> )) { die $! if $!; last; # raggiunto EOF } # ... }
$!
(errno). Se ESPR viene omessa, essa usa $_
.
$/
o
$INPUT_RECORD_SEPARATOR
[record separatore di input, NdT]).
Questa è la funzione interna che implementa l'operatore
qx/ESPR/
, ma può essere usata direttamente. L'operatore
qx/ESPR/
viene discusso con maggiore dettaglio in
I/O Operators in the perlop manpage [``Operatori di I/O'', NdT].
Notate i caratteri: dipendentemente dallo stato del socket,
vengono ricevuti sia byte (di 8-bit) che caratteri. Di default,
tutti i socket operano su byte ma per esempio se il socket è
stato modificato usando binmode()
per operare con lo strato di I/O
:utf8
(si veda la direttiva open
, the open manpage), lo I/O
opererà su caratteri Unicode codificati UTF-8, non su byte.
In maniera analoga per la direttiva :encoding
: in quel caso
può essere letto più o meno qualsiasi carattere.
redo
fa ripartire il blocco del ciclo senza valutare di
nuovo l'espressione condizionale. Il blocco continue
, se presente,
non viene eseguito. Se l'ETICHETTA viene omessa, il comando si riferisce
al ciclo più interno che lo include. Sono quei programmi che vogliono
ingannare loro stessi a proposito dell'input, ad usare di solito questo comando:
# un semplice programma che rimuove i commenti da codice Pascal # (attenzione: si assume che le stringhe non contengano { oppure } ) LINE: while (<STDIN>) { while (s|({.*}.*){.*}|$1 |) {} s|{.*}| |; if (s|{.*| |) { $anteriore = $_; while (<STDIN>) { if (/}/) { # fine del commento? s|^|$anteriore\{|; redo LINE; } } } print; }
redo
non può essere usata per fare rieseguire un blocco
che restituisce un valore, come eval {}
, sub {}
oppure do {}
,
e non dovrebbe essere usata per uscire da una operazione di grep()
o map().
Va notato che un blocco di per sé è semanticamente
identico ad un ciclo che viene eseguito una volta sola. Dunque
redo
all'interno di un tale blocco sarà effettivamente
trasformato in un costrutto iterativo.
Consultate anche continue per una illustrazione di come lavorano
last
, next
e redo
.
$_
. Il valore
restituito dipende dal tipo di cosa alla quale il riferimento
fa riferimento. I tipi interni sono:
SCALAR ARRAY HASH CODE REF GLOB LVALUE
Se l'oggetto referenziato è un'istanza di una classe, viene
restituito il nome di package. Si può pensare a ref
come
ad un operatore typeof
.
if (ref($r) eq "HASH") { print "r e` un riferimento ad un hash.\n"; } unless (ref($r)) { print "r non e` proprio un riferimento.\n"; }
Consultate anche the perlref manpage.
Il comportamente di questa funzione varia in maniera piuttosto casuale a
seconda dell'implementazione del vostro sistema. Per esempio, di solito non
funziona se utilizzata attraverso file system diversi, anche se il comando
di sistem mv a volte compensa questa carenza. Altre restrizioni includono
il funzionamento o meno su directory, file aperti, o file preesistenti.
Per i dettagli, controllate the perlport manpage e la manpage rename(2)
o l'equivalemente
sulla documentazione del vostro sistema.
$_
se ESPR non viene fornita.
VERSIONE può essere sia un argomento numerico come 5.006, che
viene poi confrontato con $]
, oppure un valore testuale nella forma di
v5.6.1, che viene poi confrontato con $^V
(conosciuto anche come
$PERL_VERSION). Se VERSIONE è più grande della versione
dell'interprete Perl corrente, viene prodotto un errore bloccante al momento
dell'esecuzione. Confrontate require con use, che può compiere
un controllo di questo tipo al momento della compilazione.
In genere, bisognerebbe evitare di specificare VERSIONE come un valore testuale nella forma v5.6.1, poiché ciò causa, con versioni vecchie del Perl che non supportano questa sintassi, dei messaggi di errore fuorvianti. Al suo posto dovrebbe essere usata la versione numerica.
require v5.6.1; # controllo di versione al momento dell'esecuzione require 5.6.1; # uguale require 5.006_001; # uguale; preferibile per compatibilitE<agrave> all'indietro
Usata diversamente, require
richiede che un file di libreria esterno venga
incluso, se non lo è stato in precedenza. Il file viene incluso con
il meccanismo do-FILE, che essenzialmente è una variante di eval
.
Ha semantiche simili alla seguente subroutine:
sub require { my ($nomefile) = @_; if (exists $INC{$nomefile}) { return 1 if $INC{$nomefile}; die "Compilazione fallita nel require"; } my ($nomefilevero,$risultato); ITER: { foreach $prefisso (@INC) { $nomefilevero = "$prefisso/$nomefile"; if (-f $nomefilevero) { $INC{$nomefile} = $nomefilevero; $risultato = do $nomefilevero; last ITER; } } die "Non trovo $nomefile in \@INC"; } if ($@) { $INC{$nomefile} = undef; die $@; } elsif (!$risultato) { delete $INC{$nomefile}; die "$nomefile non ha restituito un valore vero"; } else { return $risultato; } }
Va notato che il file non può venire incluso due volte specificando lo stesso nome.
Il file deve restituire un valore vero come ultima istruzione, per indicare
il successo dell'esecuzione di qualsiasi codice di inizializzazione, dunque
è consuetudine terminare tale file con 1;
, a meno che non si sia
sicuri che restituisca vero in ogni caso. Tuttavia, la cosa migliore è
mettere l'1;
, in caso aggiungiate altre istruzioni in un secondo momento.
Se ESPR è una bareword (*), require presume un'estensione ``.pm'' e sostituisce per voi ``::'' con ``/'' nel nome del file, in modo da rendere facile il caricamento dei moduli standard. Questo modo di caricare i moduli non comporta rischi di alterazione dello spazio dei nomi.
In altre parole, se provate questo:
require Pippo::Pluto; # una splendida bareword
La funzione require cercherà in realtà il file
``Pippo/Pluto.pm'' nelle directory specificate nell'array @INC
.
Ma se provate questa:
$class = 'Pippo::Pluto'; require $class; # $class non e` una bareword #oppure require "Pippo::Pluto"; # non e` una bareword per via delle ""
La funzione require cercherà il file ``Pippo::Pluto'' nell'array @INC e si lamenterà di non riuscirvi a trovare ``Pippo::Pluto''. In questo caso potete scrivere:
eval "require $class";
Ora che avete capito come require
cerca i file nel caso di un argomento
bareword, c'è una piccola ulteriore funzionalità che ha luogo
dietro le quinte. Prima che require
si metta a cercare una estensione
``.pm'', cercherà prima un nomefile con una estensione ``.pmc''.
Un file con questa estensione viene considerato essere del bytecode Perl
generato da B::Bytecode. Se questo file viene trovato e il suo
istante di modifica è più recente di un coincidente e non
compilato file ``.pm'', verrà caricato al posto del file non compilato
che finisce con una estensione ``.pm''.
Potete anche inserire degli hook (**) nel servizio di importazione, inserendo del codice Perl direttamente nell'array @INC. Ci sono tre tipi di hook: riferimenti a subroutine, riferimenti ad array e oggetti blessed (***).
I riferimenti a subroutine sono il caso più semplice. Quando il
sistema di inclusione esamina @NIC ed incontra una subroutine, essa viene
chiamata con due parametri: il primo è un riferimento a se stessa,
il secondo è il nome del file da includere (es. ``Pippo/Pluto.pm'').
La soubroutine deve restituire undef
oppure un filehandle, dal quale
verrà letto il file da includere. Se viene restituito undef
,
require
esaminerà i rimanenti elementi di @INC.
Se l'hook è un riferimento ad un array, il primo elemento di tale array deve essere un riferimento ad una subroutine. Questa subroutine è chiamata come sopra, ma il primo parametro è il riferimento all'array. Ciò permette di passare alcuni argomenti alla subroutine, indirettamente.
In altre parole, potete scrivere:
push @INC, \&mia_sub; sub my_sub { my ($refcodice, $nomefile) = @_; # $refcodice e` \&my_sub ... }
oppure:
push @INC, [ \&mia_sub, $x, $y, ... ]; sub mia_sub { my ($refarray, $nomefile) = @_; # Recupera $x, $y, ... my @parametri = @$refarray[1..$#$refarray]; ... }
Se l'hook è un oggetto, deve fornire un metodo INC che verrà
chiamato come sopra, ed a cui verrà passato l'oggetto stesso come
primo parametro. (Va notato che dovete indicare il nome completo della sub,
poiché esso viene sempre forzato dentro il package main
). Di seguito
è riportato un tipico schema di codice:
# In Pippo.pm package Pluto; sub new { ... } sub Pluto::INC { my ($self, $nomefile) = @_; ... }
# Nel programma principale push @INC, new Pluto(...);
Va notato che a questi hook è anche permesso impostare la voce in %INC corrispondente ai file che essi hanno caricato. Consultate %INC in the perlvar manpage.
Per un servizio di importazione ancora più potente, consultate use e the perlmod manpage.
(*) Letteralmente parola nuda, indica una parola che potrebbe essere la chiamata di una funzione (ma non ha né & all'inizio né () alla fine) ed è per questo ambigua per perl a tempo di compilazione. In assenza di use strict 'subs' (che genera errore) viene trattata come se fosse inclusa tra virgolette. [NdT]
(**) letterlamente aggancio, questo termine indica la procedura di codificare un programma che permetta all'utente di espenderlo. Ad esempio il funzionamento dei plugin di <programma con plugin> è permesso grazie a degli hook. [NdT]
(***) letteralmente santificato, consacrato, si intende di un oggetto che è stato legato al nome di un package. Si veda la funzione bless. [NdT]
continue
alla fine di un ciclo per
pulire variabili e azzerare le ricerche ??
in modo che funzionino di nuovo.
L'espressione viene interpretata come una lista di singoli caratteri (i
trattini sono ammessi per creare degli intervalli). Tutte le variabili e gli
array che cominciano per una di tali lettere vengono ripristinati al loro
stato precedente. Se l'espressione viene omessa, solo le ricerche di una
singola corrispondenza (?pattern?
) vengono azzerate per funzionare di
nuovo. Vengono pulite solo le variabili o le ricerche nel package corrente.
Restituisce sempre 1.
Esempi:
reset 'X'; # pulisce tutte le variabili X reset 'a-z'; # pulisce tutte le variabili minuscole reset; # azzera solo le ricerche ?pattern?
Chiamare un reset di "A-Z"
non è consigliabile poiché
svuoterebbe, fra le altre cose, gli array @ARGV
e @INC
e l'hash %ENV
.
Vengono reinizializzate solo le variabili di package, le variabili lessicali
non vengono toccate, ma in ogni caso queste si azzerano da sole all'uscita dallo
scope, quindi probabilmente la cosa migliore è utilizzare variabili
lessicali. Si veda my.
eval
o da un do FILE
con il valore dato
in ESPR. La valutazione di ESPR può essere fatta in contesto scalare,
lista, o vuoto, a seconda di come viene utilizzato il valore restituito, e il
contesto può variare da una invocazione ad un'altra (si veda wantarray
).
Se ESPR viene omessa, restituisce una lista vuota in contesto lista, il valore
indefinito in contesto scalare, e (ovviamente) nulla in contesto vuoto.
(Va notato che in assenza di un return
esplicito, una subroutine, eval o
do FILE restituiscono automaticamente il valore dell'ultima espressione valutata).
print reverse <>; # inversione della lista, l'ultima linea diventa la prima
undef $/; # per maggiore efficienza di <> print scalar reverse <>; # inversione dei caratteri, l'ultima linea diventa la amirp
Utilizzata senza argomenti in un contesto scalare, reverse()
inverte $_
.
Questo operatore è utile anche per invertire un hash, nonostante ci siano alcuni aspetti di cui tenere conto. Se un valore dell'hash originale è doppio, solo uno di essi può diventare una chiave nell'hash invertito. Inoltre, questa operazione deve analizzare un hash e costruirne uno nuovo, e la cosa potrebbe richiedere del tempo su un hash grande, ad esempio un file DBM.
%per_nome = reverse %per_indirizzo; # Inverte l'hash
readdir
.
$!
(errno). Se NOMEFILE viene omesso, viene usato $_
.
@conteggi = ( scalar @a, scalar @b, scalar @c );
Non c'è un operatore equivalente per forzare un espressione ad
essere interpolata in un contesto di lista perché in pratica
questo non è mai necessario. Comunque, se volete davvero farlo,
potreste usare il costrutto @{[ (una qualche espressione) ]}
, ma di
solito è sufficiente un semplice (una qualche espressione)
Dato che scalar
è un operatore unario, se accidentalmente
per ESPR utilizzate una lista con parentesi, questo ha un comportamento
analogo ad una espressione virgola scalare che valuta tutto in un
contesto vuoto meno l'ultimo elemento e che restituisce l'elemento
finale valutato in un contesto scalare. Spesso questo è quello
di cui si ha bisogno.
La seguente singola istruzione:
print uc(scalar(&pippo,$pluto)),$paperino;
è l'equivalente virtuoso di queste due:
&pippo; print(uc($pluto),$paperino);
Consultate the perlop manpage per maggiori dettagli sugli operatori unari e sull'operatore virgola.
fseek
della
libreria stdio
. FILEHANDLE può essere un'espressione il cui valore
restituisce il nome del filehandle. I valori per DA_DOVE sono: 0
per impostare
in bytes la nuova posizione a POSIZIONE, 1
per impostarla alla posizione
corrente più POSIZIONE, e 2
per impostarla a EOF (fine del file)
più POSIZIONE (generalmente negativa). Per DA_DOVE si possono utilizzare
le costanti SEEK_SET
, SEEK_CUR
e SEEK_END
(inizio del file, posizione
corrente, fine del file) definite nel modulo Fcntl. Restituisce 1
se
l'operazione è stata eseguita correttamente, 0
altrimenti.
Da notare l'espressione in bytes: anche se il file è stato impostato
per operare su caratteri (ad esempio utilizzando lo strato aperto :utf8
), tell()
restituisce uno scostamento in bytes, non in numero di caratteri (poiché
un'implementazione in tal senso renderebbe seek()
e tell()
piuttosto lente).
Per posizionarsi nel file per eseguire sysread
o syswrite
, non utilizzate
seek
, l'utilizzo del buffering rende il suo effetto sul file imprevedibile
e non portabile. Utilizzate invece sysseek
.
A causa delle regole ferree dell'ANSI C, su alcuni sistemi è necessario
un seek ogni volta che si passa da operazioni di lettura a operazioni di
scrittura. Fra le altre cose, questo potrebbe avere l'effetto di chiamare la
funzione stdio clearerr(3). Un DA_DOVE di 1
(SEEK_CUR
) può essere
utile per non muovere la posizione nel file:
seek(TEST,0,1);
Questo può anche essere utile per applicazioni che simulino il
comportamento di tail -f
. Una volta raggiunto EOF in lettura del file,
potrebbe essere necessario un seek()
per rimettere le cose a posto. Il seek
non cambia la posizione corrente, ma fa in modo che la condizione di fine
del file venga reimpostata, in modo che al prossimo <FILE>
Perl tenti
nuovamente di leggere qualcosa. O almeno così dovrebbe essere.
Se questo non dovesse funzionare (alcune implementazioni dell'IO sono particolarmente bizzose), ci potrebbe essere bisogno di qualcosa di simile a:
for (;;) { for ($poscorrente = tell(FILE); $_ = <FILE>; $poscorrente = tell(FILE)) { # cerca qualcosa e scrivilo in qualche file } sleep($un_poco); seek(FILE, $poscorrente, 0); }
readdir
.
POS dev'essere un valore restituito da telldir
. Riguardo a possibili
compattazioni di directiry, seekdir
ha gli stessi avvertimenti della
corrispondente routine della libreria di sistema.
write
o un print
senza filehandle
verrà indirizzato a questo FILEHANDLE. In secondo luogo, i riferimenti
alle variabili relative all'output si riferiranno a questo canale di output.
Ad esempio, se dovete impostare il formato di inizio modulo per più di
un canale di output, potreste fare come di seguito indicato:
select(RAPPORTO1); $^ = 'rapporto1_top'; select(RAPPORTO2); $^ = 'rapporto2_top';
FILEHANDLE può essere un'espressione il cui valore fornisce il nome del reale filehandle. Dunque:
$vecchiofh = select(STDERR); $| = 1; select($vecchiofh);
Alcuni programmatori magari preferiscono pensare ai filehandle come ad oggetti con metodi, preferendo scrivere l'ultimo esempio come:
use IO::Handle; STDERR->autoflush(1);
select(2)
con le maschere
di bit specificate, che possono essere costruite utilizzando fileno
e
vec
, su questa falsariga:
$rin = $win = $ein = ''; vec($rin,fileno(STDIN),1) = 1; vec($win,fileno(STDOUT),1) = 1; $ein = $rin | $win;
Se desiderate chiamare select su più filehandle, potreste voler scrivere una subroutine:
sub fhbits { my(@fhlist) = split(' ',$_[0]); my($bits); for (@fhlist) { vec($bits,fileno($_),1) = 1; } $bits; } $rin = fhbits('STDIN TTY SOCK');
L'idioma consueto è:
($ntrovati,$temporimasto) = select($rout=$rin, $wout=$win, $eout=$ein, $timeout);
oppure si può bloccare fino a che qualcosa non diventa pronto
$ntrovati = select($rout=$rin, $wout=$win, $eout=$ein, undef);
La maggior parte dei sistemi non si preoccupano di restituire qualcosa di
utile in $temporimasto, quindi una chiamata a select()
in contesto scalare
restituisce semplicemente $ntrovati.
Qualsiasi delle bitmask può avere valore undef (non definito). Il timeout, qualora specificato, è in secondi, che possono anche essere una frazione. Nota: non tutte le implementazioni sono in grado di restituire il $temporimasto. Se non lo sono, restituiscono sempre un $temporimasto uguale al $timeout fornito.
Potete creare uno sleep di 250 millisecondi in questo modo:
select(undef, undef, undef, 0.25);
Va notato che il fatto che select
venga riavviata dopo un segnale (ad esempio,
SIGALRM) dipende dall'implementazione. Si veda anche the perlport manpage per delle note
sulla portabilità di select
.
In caso di errore, select
si comporta come la chiamata di sistema select(2): essa
restituisce -1 ed imposta $!
.
Nota: su alcuni Unix, la chiamata di sistema select(2)
potrebbe riferire come
``pronto per la lettura'' un descrittore di file di un socket, quando in effetti non
è disponibile alcun dato, con conseguente bloccaggio a causa di una successiva lettura.
Può essere evitato utilizzando sempre il flag O_NONBLOCK sul socket. Si vedano
select(2)
and fcntl(2)
per ulteriori dettagli.
Note: on some Unixes, the select(2)
system call may report a socket file
descriptor as ``ready for reading'', when actually no data is available,
thus a subsequent read blocks. It can be avoided using always the
O_NONBLOCK flag on the socket. See select(2)
and fcntl(2)
for further
details.
ATTENZIONE: Non si dovrebbe tentare di mescolare l'I/O con buffer (come read
o <FH>) con select
, tranne per come viene permesso da POSIX, ed anche in quel
caso solo su sistemi POSIX. In quel caso dovete usare sysread
.
semctl
del System V IPC. Probabilmente dovrete prima
dichiarare
use IPC::SysV;
per ottenere le definzioni di costante corrette. Se CMD è IPC_STAT
o GETALL, allora ARG deve essere una variabile, che conserverà la struttura
semid_ds restituita o l'array di valori del semaforo. Restituisce dei valori come fa ioctl
: il valore
indefinito in caso di errore, "0 ma vero"
in caso di zero o altrimenti
l'effettivo valore restituito. ARG deve essere un vettore di interi short nativi,
che possono essere creati utilizzando pack("s!",(0)x$nsem)
.
Consultate anche la documentazione di SysV IPC in the perlipc manpage, IPC::SysV
e IPC::Semaphore
.
IPC::SysV
e IPC::SysV::Semaphore
.
pack("s!3", $numsem, $opsem, $flagsem)
. La lunghezza di STRINGAOPZ implica il
numero di operazioni sui semafori. Restituisce vero in caso di successo, oppure falso
nel caso si verifichi un errore. Ad esempio, il seguente codice attende sul semaforo
$numsem dell'id di semaforo $idsem:
$opsem = pack("s!3", $numsem, -1, 0); die "Problema con il semaforo: $!\n" unless semop($idsem, $opsem);
Per inviare un segnale al semaforo, sostituite -1
con 1
. Consultate anche
la documentazione di SysV IPC in the perlipc manpage, IPC::SysV
e IPC::SysV::Semaphore
.
sendto
.
Restituisce il numero di caratteri inviati, oppure il valore
indefinito in caso di errore. La chiamata di sistema C sendmsg(2)
non è attualmente implementata. Consultate
UDP: Message Passing in the perlipc manpage [``UPD: Passaggio di messaggi'', NdT]
per degli esempi.
Notate i caratteri: a seconda dello stato del socket, possono
essere inviati byte (8-bit) o caratteri. Di default tutti i socket operano
su byte, ma se ad esempio il socket è stato alterato utilizzando
binmode()
per operare con il layer di I/O :utf8
(si veda open, o
la direttiva open
, the open manpage), le operazioni di I/O opereranno su caratteri,
non su byte. In maniera analoga per la direttiva :encoding
: in quel caso
può essere inviato pressoché qualsiasi carattere.
0
per il processo corrente. Genera un errore bloccante se è
usata su una macchina che non implementa la chiamata POSIX
setpgid(2)
o la chiamata BSD setpgrp(2). Se gli argomenti vengono
pmessi, li imposta di default a 0,0
. Va notato che la versione BSD 4.2
di setpgrp
non accetta alcun argomento, dunque solamente
setpgrp(0,0
)> è portabile. Consultate anche POSIX::setsid()
.
Socket
. Anche i valori per LIVELLO possono essere
ottenuti da getprotobyname. VALOREOPZ potrebbe essere o una stringa compattata
oppure un intero. Un intero VALOREOPZ è un modo stenografico per dire
pack(``i'', VALOREOPZ).
Un esempio che disabilita l'algoritmo di Nagle per un socket:
use Socket qw(IPPROTO_TCP TCP_NODELAY); setsockopt($socket, IPPROTO_TCP, TCP_NODELAY, 1);
@_
se ci si trova
all'interno dello scope lessicale di subroutine e formati, e
dell'array @ARGV
se ci si trova all'interno di scope di file
oppure all'interno di scope lessicali stabiliti dai costrutti
eval ''
, BEGIN {}
, INIT {}
, CHECK {}
e END {}
.
Consultate anche unshift
, push
e pop
. shift
e
unshift
fanno all'estremità sinistra di un array
ciò che pop
and push
fanno alla parte destra.
use IPC::SysV;
per ottenere le definzioni di costante corrette. Se CMD è
IPC_STAT
, allora ARG deve essere una variabile che conserverà
la struttura shmid_ds
restituita. Restituisce dei valori come fa ioctl:
il valore indefinito in caso di errore, ``0
ma vero'' in caso di zero o
altrimenti l'effettivo valore restituito. Consultate anche SysV IPC in the perlipc manpage
e la documentazione di IPC::SysV
.
IPC::SysV
.
shmread()
effettua un taint sulla variabile. Consultate anche
SysV IPC in the perlipc manpage, la documentazione di IPC::SysV
e il
modulo IPC::Shareable
su CPAN.
shutdown(SOCKET, 0); # abbiamo finito di leggere dati shutdown(SOCKET, 1); # abbiamo finito di scrivere dati shutdown(SOCKET, 2); # abbiamo finito di usare il socket
Questo è utile nella gestione dei socket quando si
vuole far sapere all'altro lato della connessione che si ha
finito di scrivere ma non di leggere, o viceversa. È
anche una forma di chiusura più drastica di close
perché rende invalido il descrittore di file in
tutte le copie del processo ottenute tramite fork
.
$_
.
Per l'operazione di seno inverso, potete usare la funzione
Math::Trig::asin
, oppure usare questa relazione:
sub asin { atan2($_[0], sqrt(1 - $_[0] * $_[0])) }
SIGALARM
.
La funzione restituisce il numero di secondi realmente
impiegati nella pausa. Verosimilmente non potete mischiare chiamate
a alarm
e sleep
, poiché sleep
è spesso
implementata utilizzando alarm
.
Su alcuni sistemi più vecchi, la pausa potrebbe durare un intero secondo meno di quanto richiesto, a seconda della maniera con cui vengono contati i secondi. La maggior parte dei moderni sistemi si ferma per il giusto numero di secondi. Può sembrare che la pausa sia più lunga, poiché in un ambiente multitasking affollato, il vostro processo potrebbe non iniziare subito la pausa.
Per intervalli di maggior precisione di un secondo, potete usare
l'interfaccia syscall
del Perl per accedere a setitimer(2), se il
vostro sistema la supporta; altrimenti guardate select più
in alto. Anche il modulo Time::HiRes (da CPAN, e nella distribuzione
standard a partire da Perl 5.8) può esservi di aiuto.
Consultate anche la funzione pause
del modulo POSIX.
use Socket
per ottenere l'importazione delle opportune definizioni.
Consultate gli esempi in Sockets: Client/Server Communication in the perlipc manpage
[``Socket: Comunicazione Client/Server'', NdT].
Sui sistemi che supportano sui file un flag close-on-exec [chiudi-su-esecuzione, NdT], il flag sarà impostato per il descrittore di file appena aperto, come determinato dal valore di $^F. Consultate $^F in the perlvar manpage.
Sui sistemi che supportano sui file un flag close-on-exec [chiudi-su-esecuzione, NdT], il flag sarà impostato per il descrittore di file appena aperto, come determinato dal valore di $^F. Consultate $^F in the perlvar manpage.
Alcuni sistemi definiscono pipe
in termini di socketpair
,
nel quale una chiamama a pipe(Rdr, Wtr)
è essenzialmente:
use Socket; socketpair(Rdr, Wtr, AF_UNIX, SOCK_STREAM, PF_UNSPEC); shutdown(Rdr, 1); # non piu` scritture per chi legge shutdown(Wtr, 0); # non piu` letture per chi scrive
Consultate the perlipc manpage per un esempio sull'utilizzo di socketpair. Perl 5.8 e successivi emuleranno socketpair usando i socket IP su localhost nel caso che il vostro sistema implementi i socket ma non socketpair.
sort()
è indefinito.
Se NOMESUB o BLOCCO vengono omessi, ordina secondo il
confronto standard tra stringhe. Se NOMESUB viene
specificato, esso fornisce il nome di una subroutine
che restituisce un intero minore, uguale o maggiore di
0
a seconda di come gli elementi della lista devono
essere ordinati. (Gli operatori <=>
e cmp
sono
estremamente utili in tali routine).
NOMESUB può essere il nome di una variabile
scalare (senza indici di array o chiavi di hash), nel qual
caso il valore fornisce il nome (o un riferimento) della
subroutine che si deve in effetti usare. Al posto di NOMESUB
si può fornire un BLOCCO in qualità
di subroutine anonima, interna.
Se il prototipo della subroutine è ($$)
,
gli elementi da confrontare sono passati per riferimento
in @_
, come accade per una normale subroutine.
Ciò è più lento rispetto ad una subroutine
senza prototipo, dove gli elementi da confrontare sono
passati alla subroutine nelle variabili package globali
$a e $b (guardate l'esempio sottostante). Va notato che
in quest'ultimo caso è tipicamente
controproducente dichiarare $a e $b come lessicali.
In entrambi i casi la subroutine non può essere ricorsiva. I valori da confrontare sono sempre passati per riferimento, quindi non dovrebbero essere modificati.
Inoltre, non potte uscire dal blocco o dalla subroutine
di ordinamento usando uno degli operatori di controllo del
ciclo descritti in the perlsyn manpage o con goto
.
Quando use locale
è attivo, sort LISTA
ordina la lista secondo il riscontro del ``locale'' corrente.
Consultate the perllocale manpage.
sort()
restituisce gli alias alla lista originaria, così
come una variabile indice del ciclo for restituisce degli alias agli
elementi della lista.
Cioè, modificare un elemento di una lista restituita da sort()
(per esempio, in un foreach
, map
o grep
) modifica proprio
l'elemento della lista originare
much as a for loop's index
variable aliases the list elements. That is, modifying an element of a
list returned by sort()
(for example, in a foreach
, map
or grep
)
actually modifies the element in the original list. This is usually
something to be avoided when writing clear code.
Perl 5.6 e le versioni precedenti usavano l'algoritmo
quicksort per implementare l'ordinamento.
Quell'algoritmo non era stabile, e avrebbe potuto
avere un comportamento quadratico.
(Un ordinamento stabile preserva l'ordine degli
elementi in input che risultano uguali. Benché
il tempo d'esecuzione di quicksort sia O(NlogN)
in media
su tutti gli array di lunghezza N, il tempo può
essere O(N**2), ovvero comportarsi quadraticamente,
per alcuni input). Nella versione 5.7, l'implementazione
di quicksort è stata rimpiazzata da un algoritmo
mergesort stabile il cui comportamento nel caso
pessimo è O(NlogN). Ma i benchmark indicavano
che per alcuni input, su alcune piattaforme, il quicksort
originale andava più veloce. La versione 5.8 ha
una direttiva sort che consente un limitato controllo su sort.
Il suo blando controllo dell'algoritmo sottostante potrebbe
scomparire nelle prossime versioni di Perl, ma
l'abilità di caratterizzare l'input e l'output
in modi indipendenti dall'implementazione probabilmente
non lo farà. Consultate the sort manpage.
Esempi:
# ordinamento lessicale @articoli = sort @file;
# stessa cosa, ma con una routine esplicita di ordinamento @articoli = sort {$a cmp $b} @file;
# ora senza tener conto di maiuscole e minuscole @articoli = sort {uc($a) cmp uc($b)} @file;
# stessa cosa in ordine inverso @articoli = sort {$b cmp $a} @file;
# ordinamento numerico ascendente @articoli = sort {$a <=> $b} @file;
# ordinamento numerico discendente @articoli = sort {$b <=> $a} @file;
# ordina l'hash %eta per valore anziche' per chiave # usando una funzione interna @prima_gli_anziani = sort { $eta{$b} <=> $eta{$a} } keys %eta;
# ordina usando il nome della subroutine esplicito sub pereta { $eta{$a} <=> $eta{$b}; # si assume siano chiavi numeriche } @classe_ordinata = sort pereta @classe;
sub alcontrario { $b cmp $a } @harry = qw(cane gatto x Caino Abele); @george = qw(andato inseguito yz Punito Accettato); print sort @harry; # stampa AbelCaincatdogx AbeleCainocanegattox print sort alcontrario @harry; # stampa xdogcatCainAbel xgattocaneCainoAbele print sort @george, 'to', @harry; # stampa AbeleAccettatoCainoPunitoandatocanegattoinseguitotoxyz
# ordinamento inefficiente ottenuto per confronto # numerico discendente del primo numero dopo # il primo segno =, o altrimenti per confronto # di tutto il record, senza tener conto di # maiuscole e minuscole
@nuovo = sort { ($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0] || uc($a) cmp uc($b) } @vecchio;
# stessa cosa, ma in maniera molto piu` efficiente; # costruiamo indici ausiliari, per aumentare la # velocita`
@numeri = @inmaiuscolo = (); for (@vecchio) { push @numeri, /=(\d+)/; push @inmaiuscolo, uc($_); }
@nuovo = @vecchio[ sort { $numeri[$b] <=> $numeri[$a] || $caps[$a] cmp $caps[$b] } 0..$vecchio ];
# stessa cosa, ma senza variabili temporanee @nuovo = map { $_->[0] } sort { $b->[1] <=> $a->[1] || $a->[2] cmp $b->[2] } map { [$_, /=(\d+)/, uc($_)] } @vecchio;
# l'uso di un prototipo consente di usare, con sort, # qualunque subroutine di confronto (comprese le # subroutine definite in altri package) package altro; sub alcontrario ($$) { $_[1] cmp $_[0]; } # $a e $b, qui, non sono impostate
package main; @nuovo = sort altro::alcontrario @vecchio;
# stabilita` garantita, qualunque sia l'algoritmo use sort 'stable'; @nuovo = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @vecchio;
# forza l'uso di mergesort (non portabile al di # fuori della versione 5.8 di Perl) use sort '_mergesort'; # notate il _ che ne # scoraggia l'uso @nuovo = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @vecchio;
Se state usando strict, non dovete dichiarare $a e
$b come lessicali. Sono variabili globali del package.
Questo significa che se siete nel package main
e
scrivete
@articoli = sort { $b <=> $a } @file;
allora $a
e $b
sono $main::a
e $main::b
(o $::a
e $::b
), ma se siete nel package
PackagePippo
è lo stesso che scrivere
@articoli = sort { $PackagePippo::b <=> $PackagePippo::a } @file;
Si richiede che la funzione di confronto si comporti
in modo consistente. Se restituisce risultati
inconsistenti (dicendo a volte che $x[1]
è
più piccolo di $x[2]
e a volte il contrario,
per esempio) i risultati non sono ben definiti.
Poiché <=>
restituisce undef
quando uno degli operandi è
NaN
(not-a-number) [non-un-numero, NdT], e poiché sort
genererà
un errore bloccante a meno che il risultato del confronto sia definito, quando
effettuate un ordinamento con una funzione di confronto come $a <=> $b
,
state attenti alle liste che potrebbero contenere NaN
. Il seguente esempio sfrutta
il fatto che NaN != NaN
, per eliminare ogni NaN
dall'input.
@risultati = sort { $a <=> $b } grep { $_ == $_ } @input;
undef
se nessun
elemento viene rimosso. L'array si espande o rimpicciolisce come necessario. Se SCOSTAMENTO
è negativo, allora esso viene considerato a partire dalla fine dell'array. Se LUNGHEZZA
viene omesso, rimuove tutto da SCOSTAMENTO in poi. Se LUNGHEZZA è negativo, rimuove
tutti gli elementi da SCOSTAMENTO in poi, tranne -LUNGHEZZA elementi alla fine dell'array. Se
sia SCOSTAMENTO che LUNGHEZZA vengono omessi, rimuove tutto. Se SCOSTAMENTO è oltre la
fine dell'array, perl emette un avvertimento, e unisce alla fine dell'array.
Si hanno le seguenti equivalenze (assumendo $[ == 0 e $#a >= $i
):
push(@a,$x,$y) splice(@a,@a,0,$x,$y) pop(@a) splice(@a,-1) shift(@a) splice(@a,0,1) unshift(@a,$x,$y) splice(@a,0,0,$x,$y) $a[$x] = $y splice(@a,$x,1,$y)
Ad esempio, assumendo che le lunghezze degli array siano passate prima degli array:
sub aeq { # confronta due liste my(@a) = splice(@_,0,shift); my(@b) = splice(@_,0,shift); return 0 unless @a == @b; # stessa lunghezza? while (@a) { return 0 if pop(@a) ne pop(@b); } return 1; } if (&aeq($lungh,@pippo[1..$lungh],0+@pluto,@pluto)) { ... }
In un contesto scalare, restituisce il numero di campi
trovati e mette i risultati della divisione nell'array @_
.
L'uso di split in un contesto scalare è tuttavia
deprecato, poiché sovrascrive gli argomenti
della vostra subroutine.
Se ESPR viene omessa, divide la stringa $_
. Se
anche PATTERN viene omesso, divide la stringa in base
agli spazi (dopo aver saltato ciascuno spazio presente in
testa alla stringa). Qualunque cosa soddisfi PATTERN
è trattato come un delimitatore che separa i campi.
(Va notato che il delimitatore può essere più
lungo di un carattere.)
Se LIMITE viene specificato ed è positivo,
esso rappresenta il massimo numero di campi in cui
ESPR verrà divisa, però il numero
effettivo di campi restituiti dipende da quante volte
PATTERN è soddisfatto all'interno di ESPR.
Se LIMITE non viene specificato o vale zero, allora
i campi nulli in coda vengono omessi (cosa
che i potenziali utilizzatori di pop
farebbero bene
a ricordare).
Se LIMITE è negativo, allora viene trattato come
se fosse stato specificato un valore di LIMIT
arbitrariamente grande. Va notato che dividere una ESPR
che vale stringa vuota, restituisce sempre una lista
vuota, qualunque sia il LIMITE specificato.
Un pattern che corrisponde alla stringa vuota (da non
confondere con il pattern vuoto //
, che è
solo un elemento dell'insieme di pattern che corrispondono
alla stringa vuota) dividerà il valore di
ESPR in caratteri separati in corrispondenza a ciascun
punto in cui il PATTERN viene soddisfatto. Ad esempio:
print join(':', split(/ */, 'ohi la'));
produce l'output 'o:h:i:l:a'.
Come caso speciale di split
, utilizzare il pattern vuoto //
corrisponde specificamente
al match della sola stringa vuota, e non deve essere confuso con l'uso di //
per indicare ``l'ultimo pattern
soddisfatto con successo''. Così, per split
, il seguente:
print join(':', split(//, 'ohi la'));
produce l'output 'o:h:i: :l:a'.
Quando ci sono dei match di ampiezza positiva all'inizio (o alla fine) della stringa, vengono prodotti dei campi vuoti in testa (o in coda); un match di ampiezza zero all'inizio (o alla fine) della stringa non produce un campo vuoto. Per esempio:
print join(':', split(/(?=\w)/, 'ohi la!'));
produce l'output 'o:h:i :l:a!'.
Il parametro LIMITE può essere usato per dividere parzialmente una linea
($login, $passwd, $rimanente) = split(/:/, $_, 3);
Quando si assegna ad una lista, se LIMITE viene omesso, oppure è zero, Perl fornisce un valore di LIMITE che è superiore di una unità al numero di variabili contenute nella lista, per evitare del lavoro non necessario. Per la lista sopra, LIMITE sarebbe stato pari a 4, di default. In applicazioni dove il tempo è un fattore critico, è necessario non dividere in più delle parti di cui si ha veramente bisogno.
Se il PATTERN contiene delle parentesi, vengono creati elementi aggiuntivi nella lista, per ciascuna delle sottostringhe corrispondenti all'interno del delimitatore.
split(/([,-])/, "1-10,20", 3);
produce il valore di lista
(1, '-', 10, ',', 20)
Se aveste in $header l'header di un normale messaggio email Unix, potreste dividerlo in campi e rispettivi valori in questo modo:
$header =~ s/\n\s+/ /g; # mette a posto le continuazioni delle linee %hdrs = (UNIX_FROM => split /^(\S*?):\s*/m, $header);
Il pattern /PATTERN
può essere sostituito da
una espressione per specificare pattern che variano
a tempo di esecuzione. (Per effettuare una compilazione,
a tempo di esecuzione, una volta sola, usate
/$variabile/o
).
Come caso speciale, lo specificare un PATTERN costituito da uno spazio
(' '
) suddividerà in base agli spazi, esattamente come fa split
quando viene chiamata senza argomenti. Dunque, split(' ')
può
essere utilizzata per emulare il comportamento predefinito di awk,
mentre invece split(/ /)
vi restituirà tanti campi iniziali
nulli quanti sono gli spazi all'inizio della stringa.
Una split
su /\s+/
è equivalente ad una split(' ')
, tranne
che lo spazio bianco ad inizio stringa genera un primo campo nullo. Una
split
senza argomenti in realtà, internamente, è una
split(' ', $_)
.
Un PATTERN di /^/
viene trattato come se fosse /^/m
poiché,
altrimenti, non sarebbe di grande utilità.
Esempio:
open(PASSWD, '/etc/passwd'); while (<PASSWD>) { chomp; ($login, $passwd, $uid, $gid, $gcos, $home, $shell) = split(/:/); #... }
Come avviene per la normale ricerca di pattern, ogni parentesi di cattura
che non viene trovata in un'operazione di split()
sarà impostata ad
undef
al momento della restituzione dei risultati:
@campi = split /(A)|B/, "1A2B3"; # @campi e` (1, 'A', 2, undef, 3);
printf
dalla funzione
di libreria C sprintf
. Guardate qui sotto per ulteriori dettagli e consultate
sprintf(3) o printf(3) sul vostro sistema operativo per una spiegazione dei
principi generali.
Per esempio:
# Stampa un numero con fino ad 8 zeri iniziali $risultato = sprintf("%08d", $numero);
# Arrotonda un numero a 3 cifre decimali $arrotondato = sprintf("%.3f", $numero);
Perl effettua una sua formattazione sprintf
, emula la funzione C sprintf
, ma non
la utilizza (eccetto per i numeri decimali, e anche in quel caso solo i modificatori
standard sono ammessi). Come risultato, ogni estensione non standard presente nella
funzione sprintf
del vostro sistema operativo non è disponibile in Perl.
Diversamente da printf
, sprintf
non fa ciò che probabilmente ci si
aspetterebbe quando riceve un array come primo argomento. L'array viene valutato in
contesto scalare, quindi invece di utilizzare il primo elemento come formato, Perl
utilizza il numero di elementi dell'array come formato, cosa che non è quasi mai
utile.
La funzione sprintf
del Perl accetta i seguenti identificatori universalmente
riconosciuti:
%% il carattere "percento" %c il carattere con il numero indicato %s una stringa %d un intero con segno, in notazione decimale %u un intero senza segno, in notazione decimale %o un intero senza segno, in notazione ottale %x un intero senza segno, in notazione esadecimale %e un numero decimale, in notazione scientifica %f un numero decimale, in notazione fissa %g un numero decimale, in notazione %e o %f
Inoltre, Perl accetta i seguenti identificatori largamente supportati:
%X come %x, ma con lettere maiuscole %E come %e, ma con una "E" maiuscola %G come %g, ma con una "E" maiuscola (se applicabile) %b un intero senza segno, in notazione binaria %p un puntatore (restituisce l'indirizzo del valore Perl in esadecimale) %n speciale: *memorizza* il numero di caratteri nella stringa risultante nella prossima variabile dell'elenco dei parametri
Infine, per compatibilità all'indietro (e intendiamo ``indietro''), Perl accetta i seguenti identificatori, superflui ma largamente supportati:
%i sinonimo per %d %D sinonimo per %ld %U sinonimo per %lu %O sinonimo per %lo %F sinonimo per %f
Va notato che il numero delle cifre nell'esponente in notazione scientifica prodotto da %e
,
%E
, %g
e %G
per numeri con il modulo dell'esponente minore di 100 è
dipendente dal sistema: può essere tre o meno (con zero iniziali ove necessario).
In altre parole, 1.23 elevato alla novantanovesima può essere ``1.23e99'' o
``1.23e099''.
Fra il segno %
e la lettera del formato, si possono specificare alcuni attributi
aggiuntivi che modificano l'interpretazione del formato. In ordine, questi sono:
2$
. Per default,
sprintf formatterà il prossimo argomento non utilizzato nella lista, ma questo
attributo permette di prendere i parametri in ordine arbitrario.
Esempio:
printf '%2$d %1$d', 12, 34; # stampa "34 12" printf '%3$d %d %1$d', 1, 2, 3; # stampa "3 1 1"
Per esempio:
printf '<% d>', 12; # stampa "< 12>" printf '<%+d>', 12; # stampa "<+12>" printf '<%6s>', 12; # stampa "< 12>" printf '<%-6s>', 12; # stampa "<12 >" printf '<%06s>', 12; # stampa "<000012>" printf '<%#x>', 12; # stampa "<0xc>"
.
per default). Può essere utile per stampare i valori ordinali dei caratteri
in stringhe arbitrarie:
printf "%vd", "AB\x{100}"; # stampa "65.66.256" printf "versione v%vd\n", $^V; # la versione del Perl
Mettete un asterisco *
prima della v
per modificare la stringa da utilizzare al fine di
separare i numeri:
printf "indirizzo %*vX\n", ":", $addr; # indirizzo IPv6 printf "bit %0*v8b\n", " ", $bits; # stringa di bit casuale
Si può anche specificare esplicitamente il numero dell'argomento da utilizzare
come delimitatore, utilizzando ad esempio *2$v
:
printf '%*4$vX %*4$vX %*4$vX', @addr[1..3], ":"; # 3 indirizzi IPv6
*
) o da un
argomento specifico (con ad esempio *2$
):
printf '<%s>', "a"; # stampa "<a>" printf '<%6s>', "a"; # stampa "< a>" printf '<%*s>', 6, "a"; # stampa "< a>" printf '<%*2$s>', "a", 6; # stampa "< a>" printf '<%2s>', "lungo"; # stampa "<lungo>" (non tronca)
Se il campo ottenuto da *
è negativo, ha lo stesso effetto del modificatore
-
: giustificazione a destra.
.
seguito da un numero.
Per i numeri decimali, con l'eccezione di 'g' e 'G', questo indifca il numero di cifre
decimali da visualizzare (il default è 6), ad esempio:
# gli esempi sono suscettibili di variazioni in base al sistema operativo printf '<%f>', 1; # stampa "<1.000000>" printf '<%.1f>', 1; # stampa "<1.0>" printf '<%.0f>', 1; # stampa "<1>" printf '<%e>', 10; # stampa "<1.000000e+01>" printf '<%.1e>', 10; # stampa "<1.0e+01>"
Per 'g' e 'G', questo indica il numero massimo di cifre da visualizzare, includendo sia quelle prima che dopo il punto decimale, ad esempio:
# gli esempi sono suscettibili di variazioni in base al sistema operativo printf '<%g>', 1; # stampa "<1>" printf '<%.10g>', 1; # stampa "<1>" printf '<%g>', 100; # stampa "<100>" printf '<%.1g>', 100; # stampa "<1e+02>" printf '<%.2g>', 100.01; # stampa "<1e+02>" printf '<%.5g>', 100.01; # stampa "<100.01>" printf '<%.4g>', 100.01; # stampa "<100>"
Per i numeri interi, specificare una precisione implica che la formattazione del numero sarà completata con zeri fino alla larghezza specificata:
printf '<%.6x>', 1; # stampa "<000001>" printf '<%#.6x>', 1; # stampa "<0x000001>" printf '<%-10.6x>', 1; # stampa "<000001 >"
Per le stringhe, specificando una precisione, la stringa sarà troncata per entrare nella larghezza specificata:
printf '<%.5s>', "troncato"; # stampa "<tronc>" printf '<%10.5s>', "troncato"; # stampa "< tronc>"
È anche possibile prendere la precisione dal prossimo argomento utilizzando .*
:
printf '<%.6x>', 1; # stampa "<000001>" printf '<%.*x>', 6, 1; # stampa "<000001>"
Attualmente non potete ottenere la precisione da un numero specifico, ma ci si aspetta che
venga implementato in futuro utilizzando ad esempio .*2$
:
printf '<%.*2$x>', 1, 6; # NON VALIDO, ma in futuro stampera` "<000001>"
l
, h
, V
, q
, L
, o ll
. Per conversioni ad interi
(d u o x X b i D U O
), i numeri sono di norma interpretati secondo la dimensione di default
di un intero sulla vostra piattaforma (generalmente 32 o 64 bit), ma è possibile
invece utilizzare uno dei seguenti tipi standard del C, secondo il supporto del compilatore
utilizzato per compilare il Perl:
l intero interpretato come tipo C "long" o "unsigned long" h intero interpretato come tipo C "short" o "unsigned short" q, L o ll intero interpretato come tipo C "long long", "unsigned long long". o "quads" (generalmente interi a 64 bit)
[``unsigned'' sta per ``senza segno'', NdT]
L'ultimo produrrà un errore se la vostra installazione del Perl non capisce i ``quads'' (questo richiede che la vostra piattaforma supporti nativamente i quad o che il Perl sia stato specificamente compilato per supportarli). Potete verificare se il vostro Perl supporta i quad utilizzando the Config manpage:
use Config; ($Config{use64bitint} eq 'define' || $Config{longsize} >= 8) && print "quads\n";
Per conversioni a virgola mobile (e f g E F G
), i numeri sono interpretati di norma secondo
la dimensione di default di un numero a virgola mobile sulla vostra piattaforma (double o long
double), ma si può forzare l'utilizzo di 'long double' con q
, L
, o ll
se la
vostra piattaforma lo supporta. Potete verificare se il vostro Perl supporta i long double
utilizzando the Config manpage:
use Config; $Config{d_longdbl} eq 'define' && print "long double\n";
Potete verificare che il Perl considera 'long double' come la dimensione di default per i decimali a virgola mobile, utilizzando the Config manpage:
use Config; ($Config{uselongdouble} eq 'define') && print "long double sono il default\n";
È anche possibile che 'double' e 'long double' siano la stessa cosa:
use Config; ($Config{doublesize} == $Config{longdblsize}) && print "i double sono long double\n";
Il modificatore di dimensione V
non ha alcun effetto nel codice Perl, ma è
supportato per compatibilità con il codice XS; vuol dire 'utilizza la dimensione
di default per un intero (o decimale)', che è già il default nel codice
Perl.
*
per
richiedere argomenti aggiuntivi, questi vengono ``consumati'' dalla lista degli argomenti
nell'ordine in cui compaiono nel formato prima del valore da formattare. Dove un
argomento sia indicato da un indice esplicito, questo non modifica il normale ordinamento
degli argomenti (anche se l'indice specificato esplicitamente sarebbe stato comunque
il prossimo argomento).
Quindi:
printf '<%*.*s>', $a, $b, $c;
utilizza $a
per la larghezza, $b
per la precisione e $c
come valore da
formattare, mentre:
print '<%*1$.*s>', $a, $b;
utilizza $a
per la larghezza e la precisione e $b
come valore da formattare.
Di seguito qualche ulteriore esempio; attenzione che utilizzando un indice esplicito, il
segno $
può aver bisogno di essere protetto:
printf "%2\$d %d\n", 12, 34; # stampa "34 12\n" printf "%2\$d %d %d\n", 12, 34; # stampa "34 12 34\n" printf "%3\$d %d %d\n", 12, 34, 56; # stampa "56 12 34\n" printf "%2\$*3\$d %d\n", 12, 34, 3; # stampa " 34 12\n"
Se è stata data la direttiva use locale
, il carattere utilizzato per il punto
decimale nei numeri non interi è dipendente dall'impostazione LC_NUMERIC.
Consultate the perllocale manpage.
$_
. Funziona solo su quantità non negative, a meno che non abbiate
caricato il modulo standard Math::Complex.
use Math::Complex; print sqrt(-2); # stampa 1.4142135623731i
rand
.
Lo scopo della funzione è seminare [``to seed'' in iglese, NdT]
la funzione rand
affinché possa produrre una sequenza
diversa ogni volta che lanciate il vostro programma.
Se srand()
non viene chiamata esplicitamente, verrà
chiamata implicitamente la prima volta che viene usato
rand
. Comunque, questo non era il comportamento delle versioni
di Perl precedenti alla 5.004, quindi se il vostro script
si avvale di una vecchia versione dell'interprete, dovrebbe
chiamare srand
.
La maggior parte dei programmi non chiameranno affatto srand(), fatta eccezione per quelli che hanno bisogno di un punto di partenza crittograficamente robusto anziché quello di default, il quale basato sull'ora, l'ID del processo, l'allocazione di memoria o il device /dev se disponibile, è generalmente accettabile.
Potete chiamare srand($seme)
con lo stesso $seme per
riottenere la medesima sequenza da rand(), ma di solito
questo si fa esclusivamente per generare risultati
prevedibili, per fare test o debugging.
Altrimenti, non chiamate srand()
più di una volta
nei vostri programmi.
Non chiamate srand()
(vale a dire, non chiamatela senza
argomenti) più di una volta in uno script. Lo
stato interno del generatore di numeri casuali dovrebbe
contenere più entropia di quella che può essere
fornita da qualunque seme, quindi chiamare srand()
un'altra volta di fatto causa una perdita di
casualità.
La maggior parte delle implementazioni di srand
prendono un intero e troncheranno la parte decimale
senza dire nulla. Questo significa che srand(42)
produrrà di solito gli stessi risultati di
srand(42.1)
. Per andare sul sicuro, passate sempre
a srand
valori interi.
Nelle versioni di Perl precedenti alla 5.004, il seme di
default era solo il valore corrente di time
.
Non si tratta di un seme particolarmente buono, quindi
molti vecchi programmi forniscono un loro personale
valore per il seme (spesso time ^ $$
oppure
time ^ ($$ + ($$ << 15))
), ma questo non è
più necessario.
Comunque, per ragioni crittografiche, vi serve qualcosa di più casuale del seme di default. Costruire un checksum dell'output compresso di uno o più programmi che monitorano uno stato del sistema operativo che cambia di frequente è il modo che viene usato di solito. Ad esempio:
srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip`);
Se tenete particolarmente a questo aspetto, date un'occhiata
al modulo Math::TrulyRandom
su CPAN.
I programmi (come gli script CGI) che vengono usati frequentemente e che fanno uso di
time ^ $$
possono cadere preda della proprietà matematica che
a^b == (a+1)^(b+1)
un terzo delle volte. Quindi non fatelo.
$_
. Restituisce una lista nulla se la stat fallisce.
Viene tipicamente usata nella maniera seguente:
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($nomefile);
Va notato che tutti i campi sono supportati su tutti i tipi di filesystem. Ecco i significati dei campi:
0 dev numero di device del filesystem 1 ino numero di inode 2 mode modalitE<agrave> del file (tipo e permessi) 3 nlink numero di (hard) link al file 4 uid ID numerico dell'utente del proprietario del file 5 gid ID numerico del gruppo del proprietario del file 6 rdev l'identificativo di device (solo file speciali) 7 size dimensione totale del file, in byte 8 atime istante in secondi dell'ultimo accesso dall'epoch 9 mtime istante in secondi dell'ultima modifica dall'epoch 10 ctime istante in secondi di modifica dell'inode dall'epoch (*) 11 blksize dimensione preferita dei blocchi per l'I/O del filesystem 12 blocks numero di blocchi realmente allocati
(L'epoch è stato alle 00:00 del 1 gennaio 1970 GMT).
(*) Non tutti i campi sono supportati da tutti i tipi di filesystem. Degno di nota il fatto che il campo ctime non è portabile. In particolare non ci si può aspettare esso sia un ``tempo di creazione'', si veda Files and Filesystems in the perlport manpage [``File e Filesystem'', NdT] per dettagli.
Se a stat
viene passato lo speciale filehandle che consiste in un carattere di sottolineatura,
non viene eseguita alcuna stat ma vengono restituiti i contenuti correnti della struttura di
stat provenienti dall'ultima stat
, lstat
o filestat
. Ad esempio:
if (-x $file && (($d) = stat(_)) && $d < 0) { print "$file E<egrave> un file NFS eseguibile\n"; }
(Questo funziona solo su elaboratori per i quali il numero di device è negativo sotto NFS).
Visto che la modalità contiene sia il tipo di file che i suoi permessi, se volete
vedere gli effettivi permessi dovreste mascherare la porzione relativa al tipo di file e
utilizzare (s)printf usando un "%o"
.
$modalita = (stat($nomefile))[2]; printf "I permessi sono %04o\n", $modalita & 07777;
In un contesto scalare, stat
restituisce un valore booleano che indica il
successo o l'insuccesso e, in caso di succcesso, imposta l'informazione associata con lo
speciale filehandle _
.
Il modulo File::stat fornisce un conveniente meccanismo di accesso mediante nome:
use File::stat; $sb = stat($nomefile); printf "File is %s, size is %s, perm %04o, mtime %s\n", $nomefile, $sb->size, $sb->mode & 07777, scalar localtime $sb->mtime;
Potete importare le costanti (S_IF*
) e funzioni (S_IS*
) delle
modalità simboliche, dal modulo Fcntl:
use Fcntl ':mode';
$modalita = (stat($nomefile))[2];
$utente_rwx = ($modalita & S_IRWXU) >> 6; $gruppo_lettura = ($modalita & S_IRGRP) >> 3; $altri_esecuzione = $modalita & S_IXOTH;
printf "I permessi sono %04o\n", S_IMODE($modalita), "\n";
$e_setuid = $mode & S_ISUID; $e_setgid = S_ISDIR($modalita);
Potete scrivere le ultime due utilizzando gli operatori -u
e -d
. Le costanti S_IF*
comunemente disponibili sono
# Permessi: lettura, scrittura, eseczuione, per l'utente, gruppo, altri.
S_IRWXU S_IRUSR S_IWUSR S_IXUSR S_IRWXG S_IRGRP S_IWGRP S_IXGRP S_IRWXO S_IROTH S_IWOTH S_IXOTH
# Setuid/Setgid/Relativo allo sticky bit/SaveText. # Va notato che l'esatto significato di questi, e` dipendente dal sistema.
S_ISUID S_ISGID S_ISVTX S_ISTXT
# Tipi di file. Non tutti sono necessariamente disponibili sul vostro sistema.
S_IFREG S_IFDIR S_IFLNK S_IFBLK S_IFCHR S_IFIFO S_IFSOCK S_IFWHT S_ENFMT
# Le seguenti sono alias di compatibilita` per S_IRUSR, S_IWUSR, S_IXUSR.
S_IREAD S_IWRITE S_IEXEC
e le funzioni S_IF*
sono
S_IMODE($modalita) la parte di $modalita contenente i bit dei permessi e i bit di setuid/setgid/sticky
S_IFMT($modalita) la parte di $modalita contenente il tipo del file che puo` essere fatta oggetto di un and su bit con ad esempio S_IFREG o con le seguenti funzioni
# Gli operatori -f, -d, -l, -b, -c, -p e -S.
S_ISREG($modalita) S_ISDIR($modalita) S_ISLNK($modalita) S_ISBLK($modalita) S_ISCHR($modalita) S_ISFIFO($modalita) S_ISSOCK($modalita)
# Non esiste una controparte all'operatore -X ma, per il primo, # l'operatore -g e` spesso equivalente. L'ENFMT sta per # record flocking enforcement [l'applicazione forzata del flock ad un record, NdT], # una caratteristica indipendente dalla piattaforma.
S_ISENFMT($modalita) S_ISWHT($modalita)
Consultate la vostra documentazione locale di chmod(2)
e stat(2)
per maggiori dettagli sulle
costanti S_*
. Per ottenere l'informazione dello stato per un link simbolico, utilizzate la
funzione lstat
invece del file puntato dal link.
$_
se non viene
specificato) in previsione di un gran numero di corrispondenze del pattern
sulla stringa, prima che sia modificata. Può far risparmiare
tempo o meno, a seconda della natura e del numero di pattern che state
cercando, e della distribuzione delle frequenze di caratteri nella
stringa da cercare, probabilmente vale la pena di confrontare i tempi
di esecuzione con o senza study per vedere quale è più veloce.
I cicli che controllano la presenza di brevi e numerose stringhe costanti
(inclusa la parte costante di pattern più complessi) ne beneficeranno
in maggior misura. Potete avere una sola study
attiva per volta, se
``studiate'' uno scalare diverso il primo è ``non studiato''. (La maniera
in cui funziona study
è la seguente: viene generata una lista
concatenata di ogni carattere nella stringa, in modo tale da conoscere,
per esempio, dove stanno tutti i caratteri 'k'
. Da ogni stringa di
ricerca, viene selezionato il carattere più raro, secondo delle tabelle
statiche di frequenza, costruite con alcuni programmi C e del testo in
inglese. Vengono esaminate solo le posizioni che contengono questi caratteri
``più rari'').
Per esempio, ecco un ciclo che inserisce un indice producendo delle annotazioni prima di ogni linea che contiene un certo pattern:
while (<>) { study; print ".IX pippo\n" if /\bpippo\b/; print ".IX pluto\n" if /\bpluto\b/; print ".IX paperino\n" if /\bpaperino\b/; # ... print; }
Cercando /\bpippo\b
, verranno controllati solo le posizioni in $_
che
contengono p
, poiché essa è più rara di o
.
In generale, e fatta eccezione per i casi patologici, si ottiene un grande
vantaggio. L'unico problema è se viene risparmiato più tempo
di quanto se ne perde inizialmente per costruire la lista linkata.
Va notato che se dovete cercare stringhe che non conoscerete se non quando
il programma sarà eseguito, potete costruire l'intero loop come una
stringa, e valutar quest'ultima per evitare la ricompilazione dei
pattern tutte le volte. Messo assieme alla pratica di rendere indefinito
$/
per leggere interi file come fossero un solo record, il tutto può
risultare molto veloce, spesso più veloce di fgrep(1). Il codice che
segue controlla una lista di file (@files
) cercando una lista di
parole (@parole
), e stampa i nomi dei file che contengono una
corrispondenza:
$cerca = 'while (<>) { study;'; foreach $parola (@parole) { $cerca .= "++\$viste{\$ARGV} if /\\b$parola\\b/;\n"; } $cerca .= "}"; @ARGV = @files; undef $/; eval $cerca; # questa salta all'occhio $/ = "\n"; # rimette il normale delimitatore di input foreach $file (sort keys(%viste)) { print $file, "\n"; }
Consultate the perlsub manpage e the perlref manpage per dettagli sulle subroutine e i riferimenti, the attributes manpage e the Attribute::Handlers manpage per maggiori informazioni sugli attributi.
0
, oppure la qualsivoglia impostazione data a $[
(ma non è consigliabile farlo).
Se SCOSTAMENTO è un numero negativo (o più precisamente, minore di $[
), viene
contato dalla fine della stringa. Se LUNGHEZZA viene omesso, restituisce tutto ciò che
rimane fino alla fine della stringa. Se LUNGHEZZA è un numero negativo, rimuove il
numero specificato di caratteri dalla fine della stringa.
Potete usare la funzione substr()
come valore assegnabile, nel qual caso ESPR
deve essere a sua volta un valore assegnabile. Se assegnate qualcosa di più
corto di LUNGHEZZA, la stringa viene ridotta, mentre se assegnate qualcosa di più lungo
di LUNGHEZZA, la stringa viene allungata per fargli posto. Per mantenere la stringa della
stessa lunghezza, potrebbe essere necessario riempire lo spazio che avanza o eliminare i
valori in eccesso utilizzando sprintf
.
Se SCOSTAMENTO e LUNGHEZZA specificano una sottostringa che è parzialmente al di fuori
della stringa, solo la parte dentro la stringa viene restituita. Se la sottostringa è
oltre entrambi gli estremi della stringa, substr()
restituisce il valore indefinito e produce
un avvertimento. Quando viene utilizzata come valore assegnabile, specificare una sottostringa
interamente al di fuori della stringa è un errore bloccante. Di seguito un esempio che
mostra il comportamento per i casi limite:
my $nome = 'fred'; substr($nome, 4) = 'dy'; # $nome contiene ora 'freddy' my $nulla = substr $nome, 6, 2; # restituisce '' (senza warning) my $oops = substr $nome, 7; # restituisce undef, con warning substr($nome, 7) = 'gap'; # errore bloccante
Un'alternativa all'utilizzo di substr()
come valore assegnabile è quella di specificare
un valore da sostituire come quarto argomento. Questo permette di sostituire una parte di ESPR e
restituisce ciò che c'era in quella parte prima dell'operazione, proprio come fa
splice().
1
in caso
di successo, 0
altrimenti. Sui sistemi che non supportano i link simbolici, genera un
errore bloccante a tempo di esecuzione. Per controllare ciò, usate eval:
$esiste_symlink = eval { symlink("",""); 1 };
syscall
perché il Perl deve assumere che ogni puntatore a stringa
possa essere scritto dall'inizio alla fine. Se gli argomenti numerici non sono letterali e non
sono mai stati interpretati in un contesto numerico, si rende necessario sommare ad essi 0
per forzarli nell'apparire come numeri. Quanto segue emula la funzione syswrite
(o
viceversa):
require 'syscall.ph'; # potrebbe essere necessario eseguire h2ph $s = "ehila`\n"; syscall(&SYS_write, fileno(STDOUT), $s, length $s);
Va notato che il Perl supporta il passaggio fino ad un massimo di 14 argomenti per la vostra chiamata di sistema, che in pratica di solito dovrebbe essere sufficiente.
Syscall restituisce qualunque valore sia stato restituito dalla chiamata di sistema che essa ha
invocato. Se la chiamata di sistema fallice, syscall
restituisce -1
ed imposta $!
(errno). Va notato che alcune chiamate di sistema possono legittimamente restituire -1
.
La maniera approrpiata per gestire tali chiamate è quella di assegnare $!=0;
prima della chiamata e controllare il valore di $!
se syscall restituisce -1
.
C'è un problema con syscall(&SYS_pipe)
: essa restituisce il numero di file
dell'estremità in lettura della pipe che ha creato. Non c'è alcun modo per
recuperare il numero di file dell'altro capo. Si può evitare questo problema
utilizzando piuttosto pipe
.
open
del sistema operativo sottostante, con i parametri
NOMEFILE, MODALITÀ, PERMESSI.
I possibili valori e i bit di flag del parametro MODALITÀ sono dipendenti dal sistema;
sono disponibili mediante il modulo standard Fcntl
. Consultate la documentazione della
open
del vostro sistema operativo per rendersi conto di quali valori e bit di flag sono
disponibili. Potete mettere assieme diversi flag utilizzando il |
-operatore.
Alcuni dei più comuni valori sono O_RDONLY
per aprire il file in modalità di
sola lettura, O_WRONLY
per aprire il file in modalità di sola scrittura e O_RDWR
per aprire il file in modalità di lettura-scrittura.
Per ragioni storiche, alcuni valori funzionano su pressoché tutti i sistemi supportati dal perl: zero significa di sola lettura, uno significa di sola scrittura e due significa lettura/scrittura. Si è a conoscenza che questi valori non funzionano sotto OS/390 & VM/ESA Unix e sul Macintosh; è probabile che non vogliate usarli in nuovo codice.
Se il file fissato da NOMEFILE non esiste e la chiamata open
lo crea (tipicamente
perché MODALITÀ include il flag O_CREAT
), allora il valore di PERMESSI
specifica i permessi del file appena creato. Se a sysopen
omettete l'argomento PERMESSI, il
Perl utilizza il valore ottale 0666
. Questi valori dei permessi devono essere in ottale e
sono modificati dall'umask
del processo corrente.
Su molti sistemi, il flag O_EXCL
è disponibile per aprire i file in modalità
esclusiva. Questo non è eseguire un lock: l'esclusività significa in questo
contesto che se il file esiste già, sysopen()
fallisce. O_EXCL
potrebbe non funzionare
su filesystem di rete e non ha effetto a meno che venga impostato anche il flag O_CREAT
.
Impostare O_CREAT|O_EXCL
impedisce che il file venga aperto se è un link simbolico.
Questo non offre protezione ai link simbolici nel percorso del file.
Talvolta potreste voler troncare un file già esistente. Questo può essere
fatto utilizzando il flag O_TRUNC
. Il comportamento di O_TRUNC
con O_RDONLY
è
indefinito.
0644
come argomento di sysopen
andrebbe usato raramente, se non mai, poiché toglie
all'utente la possibilità di avere una umask più permissiva. È meglio
ometterlo. Consultate la voce perlfunc(1)
su umask
per maggiori dettagli.
Va notato che sysopen
dipende dalla funzione di libreria C fdopen(). Su molti sistemi UNIX,
fdopen()
è nota per fallire quando i descrittori dei file eccedono un certo valore,
tipicamente 255. Se avete bisogno di più descrittori di file, considerate la
possibilità di ricompilare il Perl in maniera che possa utilizzare la libreria sfio
o forse usando la funzione POSIX::open().
Consultate the perlopentut manpage per una gentile, garbata spiegazione sul come aprire i file.
print
, write
, seek
, tell
o eof
potrebbe causare confusione visto che il perlio o lo stdio di solito utilizzano un buffer per
i dati. Restituisce il numero di caratteri effettivamente letti, 0
alla fine del file,
oppure undef se c'è stato un errore (in quest'ultimo caso viene anche impostato $!
).
SCALARE verrà aumentato o diminuito in maniera che l'ultimo byte effettivamente letto sia
l'ultimo byte dello scalare dopo la lettura.
Uno SCOSTAMENTO può essere specificato per posizionare i dati letti da qualche
parte della stringa che non sia l'inizio. Uno SCOSTAMENTO negativo specifica il posizionamento
a quel numero di caratteri, contando a ritroso a partire dalla fine della stringa.
Uno SCOSTAMENTO positivo maggiore della lunghezza dello SCALARE ha come risultato il riempimento
della stringa alla dimensione richiesta con dei byte "\0"
prima che il risultato della lettura sia
avvenuto.
Non c'è una funzione syseof(), il che è ok, visto che comunque eof()
non
funziona molto bene sui file di device (come ttys). Usate sysread()
e controllate che il valore
restituito sia pari a 0 per decidere se si ha concluso.
Va notato che se il filehandle è stato marcato come :utf8
, verranno scritti
caratteri Unicode invece di byte (la LUNGHEZZA, lo SCOSTAMENTO e il valore restituito da
sysread()
sono in caratteri Unicode). Lo strato :encoding(...)
introduce implicitamente lo
strato :utf8
. Consultate binmode, open e la direttiva di open
, the open manpage.
0
per impostare la nuova posizione a POSIZIONE, 1
per impostarla alla posizione corrente più POSIZIONE e 2
per impostarla ad EOF
più POSIZIONE (tipicamente negativa).
Notate l'in byte: anche se il filehandle è stato impostato per operare su caratteri
(per esempio usando lo strato di I/O :utf8
), tell()
restituirà scostamenti di byte,
non scostamenti di caratteri (visto che implementare questo renderebbe sysseek()
molto lenta).
sysseek()
aggira il normale IO con buffer, dunque unire questo con i vari read (oltre a
sysread
, per esempio <>
oppure read()), print
, write
, seek
, tell
o eof
,
potrebbe causare confusione.
Per DA_DOVE, si potrebbe anche usare le costanti SEEK_SET
, SEEK_CUR
e SEEK_END
(inizio
del file, posizione corrente, fine del file) dal modulo Fcntl. L'uso delle costanti è
anche più portabile che fare affidamento su 0, 1 e 2. Per esempio, per definire una
funzione ``systell'':
use Fnctl 'SEEK_CUR'; sub systell { sysseek($_[0], 0, SEEK_CUR) }
Restituisce la nuova posizione oppure il valore indefinito in caso di insuccesso. Un valore di
posizione pari a zero viene restituito sotto forma della stringa "0 ma vero"
; dunque
sysseek
restituisce vero in caso di successo e falso in caso di insuccesso, tuttavia la
nuova posizione può ancora essere determinata facilmente.
exec LISTA
, salvo che viene eseguito prima un fork e che il
processo genitore aspetta che il processo figlio abbia ultimato. Va notato che il trattamento
degli argomenti varia in relazione al numero di argomenti. Se c'è più di un
argomento nella LISTA oppure se la LISTA è un array con più di un valore, fa
partire il programma fornendo il primo elemento della lista con argomenti forniti dal resto
della lista. Se c'è solo un argomento scalare, l'argomento viene esaminato alla ricerca
di metacaratteri di shell e, se presenti, l'intero argomento viene passato alla shell dei
comandi del sistema per l'analisi sintattica (questa è /bin/sh -c
su piattaforme
Unix ma può variare su altre piattaforme). Se nell'argomento non ci sono metacaratteri
di shell, esso viene diviso in parole e passato direttamente a execvp
che è
più efficiente.
A partire dalla versione 5.6.0, il Perl cerca di terminare le operazioni di I/O in corso su
tutti i file aperti per l'output prima di ogni operazione che potrebbe eseguire un fork, ma
questo potrebbe non essere supportato su alcune piattaforme (consultate the perlport manpage). Per essere
sicuri, dovreste impostare $|
($AUTOFLUSH nel modulo English) oppure chiamare il metodo
autoflush()
di IO::Handle
su ogni handle aperto.
Il valore restituito è lo stato di uscita del programma come restituito dalla chiamata
wait
. Per ottenere il valore di uscita corrente, fate uno shift a destra di otto (guardate
di seguito). Consultate anche exec. Questo non è quello che avete bisogno di
usare per catturare l'output da un comando, per questo dovreste usare soltanto le
virgolette inverse oppure qx//
come descritto in `STRING` in the perlop manpage. Un valore restituito
pari a -1 indica un insuccesso nel far eseguire il programma oppure un errore della chiamata di
sistema wait(2)
(esaminate $! per il motivo).
Come exec
, system
permette di mentire ad un programma riguardo al proprio nome se si usa
la sintassi system PROGRAMMA LISTA
. Di nuovo, si veda exec.
Dato che system
e le virgolette inverse bloccano SIGINT
e SIGQUIT
, eseguire un
kill sul programma che essi stanno eseguendo non interromperà realmente il
programma.
Visto che SIGINT
e SIGQUIT
vengono ignorati durante l'esecuzione di system
,
se vi aspettate che il vostro programma termini sulla ricezione di questi segnali,
avrete bisogno di fare in modo di farlo voi stessi, in base al valore restituito.
@args = ("comando", "arg1", "arg2"); system(@args) == 0 or die "system @args e` fallito: $?"
Potete controllare tutte le possibilità di insuccesso, ispezionando $?
come in
questo caso:
if ($? == -1) { print "fallimento nell'esecuzione: $!\n"; } elsif ($? & 127) { printf "figlio morto con segnale %d, %s coredump\n", ($? & 127), ($? & 128) ? 'con' : 'senza'; } else { printf "figlio uscito con valore %d\n", $? >> 8; }
oppure in maniera più portabile usando le chiamate W*() dell'estensione POSIX; si veda the perlport manpage per maggiori informazioni.
Quando gli argomenti vengono fatti eseguire mediante la shell di sistema, i risultati e i codici che vengono restituiti saranno soggetti ai suoi vezzi e proprietà. Consultate `STRING` in the perlop manpage e exec per i dettagli.
sysread()
), print
, write
, seek
, tell
o
eof
, potrebbe causare confusione visto che lo stdio di solito utilizza un buffer per i
dati. Restituisce il numero di caratteri effettivamente scritti oppure undef
se
c'è stato un errore (in questo caso viene anche impostata la variabile errno $!
).
Se la LUNGHEZZA è più grande dei dati disponibili nello scalare dopo lo SCOSTAMENTO,
verrà scritto solo il maggior numero di dati disponibili.
Uno SCOSTAMENTO può essere specificato per scrivere i dati a partire da qualche parte della stringa che non sia l'inizio. Uno SCOSTAMENTO negativo specifica la scrittura di quel numero di caratteri, contando a ritroso a partire dalla fine della stringa. Nel caso lo SCALARE sia vuoto, si può usare SCOSTAMENTO ma solo uno scostamento pari a zero.
Va notato che se il filehandle è stato marcato come :utf8
, verranno scritti
caratteri Unicode invece di byte (la LUNGHEZZA, lo SCOSTAMENTO e il valore restituito di
syswrite()
sono in caratteri Unicode codificati UTF-8). Lo strato :encoding(...)
introduce implicitamente lo strato :utf8
.
Consultate binmode, open e la direttiva di open
, the open manpage.
Va notato l'in byte: anche se il filehandle è stato impostato per operare su
caratteri (per esempio usando l'open layer :utf8
), tell()
restituirà
scostamenti di byte e non scostamenti di caratteri (questo perché renderebbe
seek()
e tell()
piuttosto lenti).
Il valore restituito da tell()
per i flussi standard come lo STDIN, dipende dal sistema
operativo: potrebbe restituire -1 o qualcos'altro. tell()
sulle pipe, fifo e socket di
solito restituisce -1.
Non c'è una funzione systell
. Per questo, si usi sysseek(FH, 0, 1)
.
Non usate tell()
(o altre operazione di I/O che usano un buffer) su un filehandle che sia
stato manipolato da sysread(), syswrite()
o sysseek(). Queste funzioni ignorano l'utilizzo di
buffer mentre tell()
no.
readdir
su DIRHANDLE. Il valore
ottenuto può essere passato a seekdir
per accedere ad una particolare
locazione in una directory. telldir
ha gli stessi avvertimenti sulla directory
compaction [compattazione della directory, NdT] della corrispondente routine della
libreria di sistema.
new
della classe (cioè TIESCALAR
, TIEHANDLE
, TIEARRAY
o TIEHASH
).
Tipicamente questi sono argomenti simili a quelli che si potrebbero passare alla funzione
dbm_open()
del C. L'oggetto restituito dal metodo new
è anche restituito
dalla funzione tie
, e risulta utile per accedere ad altri metodi in NOMECLASSE.
Va notato che funzioni come keys
e values
possono restituire liste molto grandi
quando vengono usate su oggetti grandi, come file DBM. Potreste preferire l'utilizzo
della funzione each
per iterare su tali strutture. Ad esempio:
# stampa gli offset del file history use NDBM_File; tie(%HIST, 'NDBM_File', '/usr/lib/news/history', 1, 0); while (($chiave,$val) = each %HIST) { print $chiave, ' = ', unpack('L',$val), "\n"; } untie(%HIST);
Una classe che implementa un hash deve contenere i seguenti metodi:
TIEHASH nomeclasse, LISTA FETCH this, chiave STORE this, chiave, valore DELETE this, chiave CLEAR this EXISTS this, chiave FIRSTKEY this NEXTKEY this, ultimachiave DESTROY this UNTIE this
Un classe che implementa un array ordinario deve contenere i seguenti metodi:
TIEARRAY nomeclasse, LISTA FETCH this, chiave STORE this, chiave, valore FETCHSIZE this STORESIZE this, conteggio CLEAR this PUSH this, LISTA POP this SHIFT this UNSHIFT this, LISTA SPLICE this, scostamento, lunghezza, LISTA EXTEND this, conteggio DESTROY this UNTIE this
Un classe che implementa un file handle deve contenere i seguenti metodi:
TIEHANDLE nomeclasse, LISTA READ this, scalare, lunghezza, scostamento READLINE this GETC this WRITE this, scalare, lunghezza, scostamento PRINT this, LISTA PRINTF this, formato, LISTA BINMODE this EOF this FILENO this SEEK this, posizione, dadove TELL this OPEN this, modo, LISTA CLOSE this DESTROY this UNTIE this
Una classe che implementa uno scalare deve contenere i seguenti metodi:
TIESCALAR nomeclasse, LISTA FETCH this, STORE this, valore DESTROY this UNTIE this
Non è necessario implementare tutti i metodi sopra descritti. Consultate the perltie manpage, the Tie::Hash manpage, the Tie::Array manpage, the Tie::Scalar manpage e the Tie::Handle manpage.
A differenza di dbmopen
, la funzione tie
non chiamerà use o require per
voi su un modulo, dovrete farlo voi esplicitamente. Consultate the DB_File manpage o il modulo
Config per delle interessanti implementazioni di tie
.
Per ulteriori dettagli consultate the perltie manpage, tied VARIABLE [``VARIABILE legata'', NdT].
tie
che ha legato la
variabile al package.) Restituisce il valore indefinito se VARIABILE non è
legata ad un package.
gmtime
e localtime
. Sulla maggior parte dei sistemi, l'epoch
è 00:00:00 UTC, Gennaio 1, 1970; una importante eccezione è costituita da
Mac OS Classic il quale utilizza come epoch 00:00:00, January 1, 1904 nella zona temporale del
locale corrente.
Per misurare il tempo con precisione maggiore di un secondo, potete utilizzare il modulo
Time::HiRes (da CPAN e, a partire dal Perl 5.8, parte della distribuzione standard),
oppure se avete a disposizione gettimeofday(2), potreste essere in grado di utilizzare
l'interfaccia syscall
del Perl. Consultate the perlfaq8 manpage per dettagli.
($utente,$sistema,$figlioutente,$figliosistema) = times;
In un contesto scalare, times
restituisce $utente
.
y///
. Consultate the perlop manpage.
Il comportamento è indefinito se LUNGHEZZA è più grande della lunghezza del file.
\U
nelle stringhe tra apici doppi. Rispetta
l'LC_CTYPE locale corrente se use locale
è attivo. Consultate the perllocale manpage e
the perlunicode manpage per maggiori dettagli riguardo locale e il supporto a Unicode. Non tenta
di eseguire un titlecase mapping [trasformazione in lettera maiuscola per Unicode, NdT]
sulle lettere iniziali delle parole. Per quello, consultate ucfirst
.
Se ESPR viene omessa, la funzione usa $_
.
\l
nelle stringhe racchiuse tra apici doppi. Rispetta il locale
LC_CTYPE corrente se è stato specificato use locale
. Consultate the perllocale manpage
e the perlunicode manpage per maggiori dettagli sul supporto per il locale e l'Unicode.
Se ESPR viene omessa, la funzione usa $_
.
Il permesso Unix rwxr-x---
viene rappresentato come tre insiemi di tre bit oppure con
tre cifre ottali: 0750
(il primo 0 indica l'ottale e non è una delle cifre).
Il valore di umask
è quel numero che rappresenta i bit dei permessi
disabilitati. I valori dei permessi (o ``modalità'') che passate a mkdir
o
sysopen
sono modificati dall'umask dunque anche se dite a sysopen
di creare un
file con permessi 0777
, se l'umask è 0022
allora il file verrà in
effetti creato con permessi 0755
. Se l'umask
fosse 0027
(il gruppo non
può scrivere, i restanti non possono leggere, scrivere od eseguire) allora
passare 0666
a sysopen
creerebbe un file con modalità 0640
(0666 &~027
è 0640
).
Ecco alcuni consigli: fornite una modalità di creazione di 0666
per file
ordinari (in sysopen
) ed una di 0777
per le directory (in mkdir
) e i file
eseguibili. Questo dà agli utenti la libertà di scelta: se vogliono file
protetti sceglieranno umask di 022
, 027
o anche la particolare ed antisociale mask
di 077
. I programmi, se non in rari casi, non dovrebbero prendere decisioni sulla
policy che sarebbe meglio fosse lasciata all'utente. L'eccezione a questo fatto si ha
nello scrivere file che devono essere mantenuti privati: file di mail, cookie del
browser web, file .rhosts e così via.
Se umask(2)
non è implementata sul vostro sistema e si sta cercando di
restringere l'accesso a se stessi (cioè, (ESPR & 0700) > 0), produce un
errore bloccante a tempo di esecuzione. Se umask(2)
non è implementata e non si
sta cercando di restringere l'accesso a se stessi, restituisce undef
.
Ricordatevi che un umask è un numero, generalmente fornito in ottale; non è una stringa di cifre ottali. Si veda anche oct se tutto ciò che si ha è una stringa.
@
), un hash (utilizzando %
), una subrotuine
(utilizzando &
), oppure un typeglob (utilizzando *
). (undef $hash{$chiave}
probabilmente non farà ciò che ci si aspetta su molte variabili
predefinite o valori di liste DBM, dunque non fatelo; si veda delete).
Restituisce sempre il valore indefinito. Potete omettere l'ESPR, in tal caso non
viene reso indefinito niente, ma otterrete ancora un valore indefinito che si potreste,
per esempio, restituire da una subroutine, assegnare ad una variabile o passare come
parametro. Esempi:
undef $pippo; undef $pluto{'nomeassurdo'}; # Confrontate con: delete $pippo{'nomeassurdo'}; undef @ary; undef %hash; undef &miasub; undef *xyz; # distrugge $xyz, @xyz, %xyz, &xyz, ecc. return (wantarray ? (undef, $msgerr) : undef) if $lo_hanno_saltato; select undef, undef, undef, 0.25; ($a, $b, undef, $c) = &pippo; # Ignora il terzo valore restituito
Va notato che questo è un operatore unario, non un operatore di lista.
$cnt = unlink 'a', 'b', 'c'; unlink @dacancellare; unlink <*.bak>;
Nota: unlink
non tenterà di cancellare le directory a meno che non siate
superuser e al Perl non venga passato il flag -U. Anche se queste condizioni risultano
soddisfatte, sappiate che effettuare un unlink su una directory poè danneggiare
seriamente il vostro filesystem. Infine, usare unlink
sulle directory non è
supportato su molti sistemi operativi. Usate rmdir
al suo posto.
Se LISTA viene omessa, viene usato $_
.
unpack
è l'inverso di pack
: prende una stringa e la espande in una lista di
valori. (In contesto scalare restituisce solamente il primo valore generato).
La stringa viene divisa in pezzi come descritto da TEMPLATE. Ogni pezzo viene convertito
separatamente in un valore. Solitamente, la stringa è un risultato di pack
,
oppure i suoi byte rappresentano una struttura C di un qualche tipo.
TEMPLATE ha lo stesso formato che nella funzione pack
. Ecco una subroutine che trova
una sottostringa:
sub substr { my($cosa,$dove,$quanto) = @_; unpack("x$dove a$quanto", $cosa); }
e poi c'è:
sub ordinale { unpack("c",$_[0]); } # come ord()
In aggiunta ai campi permessi da pack(), potete far precedere a ciascun campo un
%<numero> per indicare che desiderate un checksum di <numero>-bit degli elementi
anziché i reali elementi. Il checksum predefinito è di 16 bit.
Il checksum è calcolato sommando i valori numerici dei valori espandi (per le
stringhe viene considerata la somma di ord($carattere)
, per i bit la somma degli zero
e degli uno).
Per esempio, il seguente codice calcola lo stesso numero del programma sum di System V:
$checksum = do { local $/; # slurp! unpack("%32C*",<>) % 65535; };
Il seguente codice conta in maniera efficiente il numero di bit impostati in un vettore di bit:
$bitimpostati = unpack("%32b*", $maschera_di_selezione);
I formati p
e P
devono essere usati con cura. Dato che Perl non ha alcun modo di
controllare se il valore passato ad unpack()
corrisponda ad una valida locazione di
memoria, passare un puntatore che non si è certi sia valido probabilmente
porterà a conseguenze disastrose.
Se ci sono più codici per pack oppure se l conteggio delle ripetizioni di un
campo o di un gruppo è maggiore di quanto il rimanente input permetta, il
risultato non è ben definito: in alcuni casi, il conto delle ripetizioni viene
decrementato, oppure unpack()
produrrà stringhe nulle o zeri oppure
terminerà con un errore. Se la stringa in input è più lunga di
quella descritta da TEMPLATE, la parte in più viene ignorata.
Consultate pack per ulteriori esempi e note.
tie
).
Non ha effetto se sulla variabile non è stato fatto un tie
.
shift
. Oppure l'opposto di un push
, a seconda di come lo si
guardi. Antepone una lista nella parte anteriore dell'array e restituisce il nuovo numero
di elementi nell'array.
unshift(@ARGV, '-e') unless $ARGV[0] =~ /^-/;
Va notato che LISTA viene anteposta per intero, non un elemento alla volta, dunque gli
elementi preposti si trovano nel medesimo ordine. Usate reverse
per effettuare
l'inversione.
BEGIN { require Modulo; import Modulo LISTA; }
tranne per il fatto che Modulo deve essere una bareword (*).
VERSIONE può essere sia un argomento numerico come 5.006, il quale viene poi
confrontato con $]
, oppure un valore testuale nella forma di v5.6.1, che viene poi
confrontato con $^V
(conosciuto anche come $PERL_VERSION). Se VERSIONE è
più grande della versione dell'interprete Perl corrente, viene prodotto un errore
bloccante al momento dell'esecuzione. Fate un confronto con require, che
può compiere un controllo di questo tipo al momento dell'esecuzione.
In genere, bisognerebbe evitare di specificare VERSIONE come un valore testuale nella forma v5.6.1, poiché ciò causa, sotto versioni vecchie del Perl che non supportano questa sintassi, dei messaggi di errore fuorvianti. Al suo posto dovrebbe essere usata la versione numerica.
use v5.6.1; # controllo di versione al momento della compilazione use 5.6.1; # uguale use 5.006_001; # uguale; preferibile per compatibilita` all'indietro
Questo è spesso utile se avete bisogno di controllare la versione di Perl
corrente prima prima di chiamare use
per usare dei moduli di libreria che avere
modificato in maniera incompatibile con le versioni più vecchie di Perl.
(Cerchiamo di non fare questo più di quanto siamo costretti).
Il blocco BEGIN
forza require
ed import
ad essere eseguiti al momento della
compilazione. L'istruzione require
assicura che il modulo venga caricato in memoria,
se non lo è già. L'istruzione import
non è integrata in
Perl--è semplicemente una normale chiamata ad un metodo statico all'interno del
package Module
, allo scopo di dire al modulo di importare la lista di caratteristiche
nel package corrente. Il modulo può implementare il suo metodo import
come
desidera, anche se la maggior parte dei moduli decidono semplicemente di derivarlo,
utilizzando l'ereditarietà, dalla classe Exporter
definita nel modulo
Exporter
. Consultate the Exporter manpage. Se non si riesce a trovare alcun metodo import
,
la chiamata viene saltata.
Se non volete chiamare il metodo import
del package (per esempio allo scopo di evitare
l'alterazione del vostro spazio dei nomi), fornite esplicitamente una lista vuota:
use Modulo ();
Questo equivale esattamente a
BEGIN { require Modulo }
Se tra Modulo e LISTA è presente l'argomento VERSIONE, allora use
chiamerà il metodo VERSIONE nella classe Modulo passandogli come argomento la
versione indicata. Il metodo di default VERSIONE, ereditato dalla classe UNIVERSAL, muore
se la versione indicata è maggior del valore della variabile $Modulo::VERSIONE
.
Inoltre, c'è una distinzione tra omettere LISTA (import
chiamata senza
argomenti) ed un'esplicita LISTA vuota ()
(import
non è chiamata). Va
notato che non c'è alcuna virgola dopo VERSIONE!
Siccome quest'interfaccia è molto aperta, i pragma (direttive del compilatore) sono anch'essi implementati in questo modo. Le direttive implementate al momento sono:
use constant; use diagnostics; use integer; use sigtrap qw(SEGV BUS); use strict qw(subs vars refs); use subs qw(afunc blurfl); use warnings qw(all); use sort qw(stable _quicksort _mergesort);
Alcuni di questi pseudomoduli importano le semantiche nel corrente blocco dello scope
(ad esempio strict
o integer
, a differenza dei moduli ordinari che importano
simboli nel package corrente (che hanno effetti fino alla fine del file)).
C'è un corrispondente comando no
che annulla l'importazione di quanto
importate da use
, cioè chiama unimport Modulo LISTA
anziché
import
.
no integer; no strict 'refs'; no warnings;
Consultate the perlmodlib manpage per una lista di moduli e di direttive standard. Consultate
the perlrun manpage per le opzioni da linea di comando -M
e -m
, che rendono accessibili le
funzionalità di use
dalla linea di comando.
(*) Letteralmente parola nuda, indica una parola che potrebbe essere la chiamata di una funzione (ma non ha né & all'inizio né () alla fine) ed è per questo ambigua per perl a tempo di compilazione. In assenza di use strict 'subs' (che genera errore) viene trattata come se fosse inclusa tra virgolette. [NdT]
touch(1)
se il file esiste già ed appartiene
all'utente che sta eseguendo il programma:
#!/usr/bin/perl $tempoa = $tempom = time; utime $tempoa, $tempom, @ARGV;
A partire dal perl 5.7.2, se i primi due elementi della lista sono undef
, allora la
funzione utime(2)
nella libreria C verrà chiamata con un secondo argomento null.
Sulla maggior parte dei sistemi, questo imposterà i tempi di accesso e modifica
del file all'istante corrente (equivalente cioè al suddetto esempio) e funzionerà
anche sui file di altri utenti dove avrete i permessi di scrittura:
utime undef, undef, @ARGV;
Con NFS userà la data del server NFS, non la data della macchina locale. Se sussiste un problema di sincronizzazione, allora il server NFS e la macchina locale avranno date diverse. Il comando Unix touch in effetti userà questa forma anziché quella mostrata nel primo esempio.
Va notato che solo passare uno dei primi due elementi come undef
risulterà equivalente
al passarlo come 0, e non avrà lo stesso effetto descritto quando essi sono entrambi
undef. In questo caso verrà fatto scattare un avvertimento per il valore indefinito.
I valori sono restituiti in un ordine apparentemente casuale. Tale ordine casuale
saràs oggetto a cambiamenti nelle future versioni di perl, ma è garantito
essere lo stesso ordine che producono le funzioni keys
e each
sullo stesso
(non modificato) hash. Per ragioni di sicurezza, a partire dal Perl 5.8.1 l'ordinamento
è differente anche tra diverse esecuzioni di Perl (consultate
Algorithmic Complexity Attacks in the perlsec manpage [``Attacchi di Complessità Algoritmica'', NdT]).
Come effetto collaterale, la chiamata a values()
reimposta l'iteratore interno dell'HASH,
si veda each. (In particolare, una chiamata a values()
in un contesto vuoto, reimposta
l'iteratore senza alcun costo computazionale aggiuntivo).
Va notato che i valori non vengono copiati, il che significa che modificare essi modifica i contenuti dell'hash:
for (values %hash) { s/pippo/pluto/g } # modifica i valori di %hash for (@hash{keys %hash}) { s/pippo/pluto/g } # stessa cosa
Se NUMERO_DI_BIT è 8, ``elementi'' coincide con i byte della stringa di input.
Se NUMERO_DI_BIT è 16 o più, i byte della stringa di input sono
raggruppati in pezzi di dimensione NUMERO_DI_BIT/8 ed ogni gruppo viene convertito in un
numero come con pack()/unpack()
con i formati big-endian n
/N
(analogamente per
NUMERO_DI_BIT==64). Consultate pack per i dettagli.
Se il numero di bit è 4 o meno, la stringa viene spezzata in bytes, poi i bit di
ogni byte sono spezzati in 8/NUMERO_DI_BIT gruppi. I bit di un byte sono numerati alla
maniere dei little-endian, come in 0x01
, 0x02
, 0x04
, 0x08
, 0x10
, 0x20
,
0x40
, 0x80
. Per esempio, spezzare il singolo byte di input chr(0x36)
in due
gruppi, dà una lista (0x6, 0x3)
; spezzarlo in 4 gruppi dà
(0x2, 0x1, 0x3, 0x0)
.
vec
può anche essere assegnato, nel qual caso le parentesi sono necessarie per
dare all'espressione la corretta precedenza, come in
vec($immagine, $max_x * $x + $y, 8) = 3;
Se l'elemento selezionato è al di fuori della stringa, viene restituito il valore 0. Se un elemento viene scritto oltre la fine della stringa, il Perl per prima cosa estenderà la stringa con un numero adeguato di byte a zero. È un errore il tentare di scrivere oltre l'inizio della stringa (cioè uno SCOSTAMENTO negativo).
La stringa non dovrebbe contenere alcun carattere con valore > 255 (che può
avvenire solo se si sta usando la codifica UTF8). Se lo contiene, sarà trattato
come qualcosa che non è codificata UTF8. Quando vec
viene assegnato, anche
altre parti del programma non considereranno la stringa come codificata UTF8. In altre
parole, se si hanno tali caratteri nelle stringhe, vec()
opererà sulla stringa di
byte effettiva e non sulla stringa di caratteri concettuale.
Le stringhe create con vec
possono anche venir manipolate con gli operatori logici
|
, &
, ^
e ~
. Questi operatori assumeranno che quando entrambi gli operandi
sono stringhe, sarà richiesta un'operazione a vettore di bit. Si veda
Bitwise String Operators in the perlop manpage [``Operatori di stringa bitwise'', NdT].
Il codice seguente costruirà una stringa ASCII che recita 'PerlPerlPerl'
.
I commenti mostrano la stringa dopo ogni passo. Va notato che questo codice funziona nella
stessa maniera sia su elaboratori big-endian che little-endian.
my $pippo = ''; vec($pippo, 0, 32) = 0x5065726C; # 'Perl'
# $pippo eq "Perl" eq "\x50\x65\x72\x6C", 32 bit print vec($pippo, 0, 8); # prints 80 == 0x50 == ord('P')
vec($pippo, 2, 16) = 0x5065; # 'PerlPe' vec($pippo, 3, 16) = 0x726C; # 'PerlPerl' vec($pippo, 8, 8) = 0x50; # 'PerlPerlP' vec($pippo, 9, 8) = 0x65; # 'PerlPerlPe' vec($pippo, 20, 4) = 2; # 'PerlPerlPe' . "\x02" vec($pippo, 21, 4) = 7; # 'PerlPerlPer' # 'r' e` "\x72" vec($pippo, 45, 2) = 3; # 'PerlPerlPer' . "\x0c" vec($pippo, 93, 1) = 1; # 'PerlPerlPer' . "\x2c" vec($pippo, 94, 1) = 1; # 'PerlPerlPerl' # 'l' e` "\x6c"
Per trasformare un vettore di bit in una striga o lista di 0 e 1, si usino queste:
$numero_di_bit = unpack("b*", $vettore); @numero_di_bit = split(//, unpack("b*", $vettore));
Se siete a conoscenza dell'esatta lunghezza in bit, la si può usare al posto del
*
.
Ecco un esempio per illustrare come i bit vanno effettivamente a posto:
#!/usr/bin/perl -wl
print <<'EOT'; 0 1 2 3 unpack("V",$_) 01234567890123456789012345678901 ------------------------------------------------------------------ EOT
for $w (0..3) { $ampiezza = 2**$w; for ($spostamento=0; $spostamento < $ampiezza; ++$spostamento) { for ($distanza=0; $distanza < 32/$ampiezza; ++$distanza) { $str = pack("B*", "0"x32); $numero_di_bit = (1<<$spostamento); vec($str, $distanza, $ampiezza) = $numero_di_bit; $ris = unpack("b*",$str); $val = unpack("V", $str); write; } } }
format STDOUT = vec($_,@#,@#) = @<< == @######### @>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $distanza, $ampiezza, $numero_di_bit, $val, $ris . __END__
Indifferente all'architettura dell'elaboratore sul quale viene eseguito, l'esempio soprastante dovrebbe stampare la seguente tabella:
0 1 2 3 unpack("V",$_) 01234567890123456789012345678901 ------------------------------------------------------------------ vec($_, 0, 1) = 1 == 1 10000000000000000000000000000000 vec($_, 1, 1) = 1 == 2 01000000000000000000000000000000 vec($_, 2, 1) = 1 == 4 00100000000000000000000000000000 vec($_, 3, 1) = 1 == 8 00010000000000000000000000000000 vec($_, 4, 1) = 1 == 16 00001000000000000000000000000000 vec($_, 5, 1) = 1 == 32 00000100000000000000000000000000 vec($_, 6, 1) = 1 == 64 00000010000000000000000000000000 vec($_, 7, 1) = 1 == 128 00000001000000000000000000000000 vec($_, 8, 1) = 1 == 256 00000000100000000000000000000000 vec($_, 9, 1) = 1 == 512 00000000010000000000000000000000 vec($_,10, 1) = 1 == 1024 00000000001000000000000000000000 vec($_,11, 1) = 1 == 2048 00000000000100000000000000000000 vec($_,12, 1) = 1 == 4096 00000000000010000000000000000000 vec($_,13, 1) = 1 == 8192 00000000000001000000000000000000 vec($_,14, 1) = 1 == 16384 00000000000000100000000000000000 vec($_,15, 1) = 1 == 32768 00000000000000010000000000000000 vec($_,16, 1) = 1 == 65536 00000000000000001000000000000000 vec($_,17, 1) = 1 == 131072 00000000000000000100000000000000 vec($_,18, 1) = 1 == 262144 00000000000000000010000000000000 vec($_,19, 1) = 1 == 524288 00000000000000000001000000000000 vec($_,20, 1) = 1 == 1048576 00000000000000000000100000000000 vec($_,21, 1) = 1 == 2097152 00000000000000000000010000000000 vec($_,22, 1) = 1 == 4194304 00000000000000000000001000000000 vec($_,23, 1) = 1 == 8388608 00000000000000000000000100000000 vec($_,24, 1) = 1 == 16777216 00000000000000000000000010000000 vec($_,25, 1) = 1 == 33554432 00000000000000000000000001000000 vec($_,26, 1) = 1 == 67108864 00000000000000000000000000100000 vec($_,27, 1) = 1 == 134217728 00000000000000000000000000010000 vec($_,28, 1) = 1 == 268435456 00000000000000000000000000001000 vec($_,29, 1) = 1 == 536870912 00000000000000000000000000000100 vec($_,30, 1) = 1 == 1073741824 00000000000000000000000000000010 vec($_,31, 1) = 1 == 2147483648 00000000000000000000000000000001 vec($_, 0, 2) = 1 == 1 10000000000000000000000000000000 vec($_, 1, 2) = 1 == 4 00100000000000000000000000000000 vec($_, 2, 2) = 1 == 16 00001000000000000000000000000000 vec($_, 3, 2) = 1 == 64 00000010000000000000000000000000 vec($_, 4, 2) = 1 == 256 00000000100000000000000000000000 vec($_, 5, 2) = 1 == 1024 00000000001000000000000000000000 vec($_, 6, 2) = 1 == 4096 00000000000010000000000000000000 vec($_, 7, 2) = 1 == 16384 00000000000000100000000000000000 vec($_, 8, 2) = 1 == 65536 00000000000000001000000000000000 vec($_, 9, 2) = 1 == 262144 00000000000000000010000000000000 vec($_,10, 2) = 1 == 1048576 00000000000000000000100000000000 vec($_,11, 2) = 1 == 4194304 00000000000000000000001000000000 vec($_,12, 2) = 1 == 16777216 00000000000000000000000010000000 vec($_,13, 2) = 1 == 67108864 00000000000000000000000000100000 vec($_,14, 2) = 1 == 268435456 00000000000000000000000000001000 vec($_,15, 2) = 1 == 1073741824 00000000000000000000000000000010 vec($_, 0, 2) = 2 == 2 01000000000000000000000000000000 vec($_, 1, 2) = 2 == 8 00010000000000000000000000000000 vec($_, 2, 2) = 2 == 32 00000100000000000000000000000000 vec($_, 3, 2) = 2 == 128 00000001000000000000000000000000 vec($_, 4, 2) = 2 == 512 00000000010000000000000000000000 vec($_, 5, 2) = 2 == 2048 00000000000100000000000000000000 vec($_, 6, 2) = 2 == 8192 00000000000001000000000000000000 vec($_, 7, 2) = 2 == 32768 00000000000000010000000000000000 vec($_, 8, 2) = 2 == 131072 00000000000000000100000000000000 vec($_, 9, 2) = 2 == 524288 00000000000000000001000000000000 vec($_,10, 2) = 2 == 2097152 00000000000000000000010000000000 vec($_,11, 2) = 2 == 8388608 00000000000000000000000100000000 vec($_,12, 2) = 2 == 33554432 00000000000000000000000001000000 vec($_,13, 2) = 2 == 134217728 00000000000000000000000000010000 vec($_,14, 2) = 2 == 536870912 00000000000000000000000000000100 vec($_,15, 2) = 2 == 2147483648 00000000000000000000000000000001 vec($_, 0, 4) = 1 == 1 10000000000000000000000000000000 vec($_, 1, 4) = 1 == 16 00001000000000000000000000000000 vec($_, 2, 4) = 1 == 256 00000000100000000000000000000000 vec($_, 3, 4) = 1 == 4096 00000000000010000000000000000000 vec($_, 4, 4) = 1 == 65536 00000000000000001000000000000000 vec($_, 5, 4) = 1 == 1048576 00000000000000000000100000000000 vec($_, 6, 4) = 1 == 16777216 00000000000000000000000010000000 vec($_, 7, 4) = 1 == 268435456 00000000000000000000000000001000 vec($_, 0, 4) = 2 == 2 01000000000000000000000000000000 vec($_, 1, 4) = 2 == 32 00000100000000000000000000000000 vec($_, 2, 4) = 2 == 512 00000000010000000000000000000000 vec($_, 3, 4) = 2 == 8192 00000000000001000000000000000000 vec($_, 4, 4) = 2 == 131072 00000000000000000100000000000000 vec($_, 5, 4) = 2 == 2097152 00000000000000000000010000000000 vec($_, 6, 4) = 2 == 33554432 00000000000000000000000001000000 vec($_, 7, 4) = 2 == 536870912 00000000000000000000000000000100 vec($_, 0, 4) = 4 == 4 00100000000000000000000000000000 vec($_, 1, 4) = 4 == 64 00000010000000000000000000000000 vec($_, 2, 4) = 4 == 1024 00000000001000000000000000000000 vec($_, 3, 4) = 4 == 16384 00000000000000100000000000000000 vec($_, 4, 4) = 4 == 262144 00000000000000000010000000000000 vec($_, 5, 4) = 4 == 4194304 00000000000000000000001000000000 vec($_, 6, 4) = 4 == 67108864 00000000000000000000000000100000 vec($_, 7, 4) = 4 == 1073741824 00000000000000000000000000000010 vec($_, 0, 4) = 8 == 8 00010000000000000000000000000000 vec($_, 1, 4) = 8 == 128 00000001000000000000000000000000 vec($_, 2, 4) = 8 == 2048 00000000000100000000000000000000 vec($_, 3, 4) = 8 == 32768 00000000000000010000000000000000 vec($_, 4, 4) = 8 == 524288 00000000000000000001000000000000 vec($_, 5, 4) = 8 == 8388608 00000000000000000000000100000000 vec($_, 6, 4) = 8 == 134217728 00000000000000000000000000010000 vec($_, 7, 4) = 8 == 2147483648 00000000000000000000000000000001 vec($_, 0, 8) = 1 == 1 10000000000000000000000000000000 vec($_, 1, 8) = 1 == 256 00000000100000000000000000000000 vec($_, 2, 8) = 1 == 65536 00000000000000001000000000000000 vec($_, 3, 8) = 1 == 16777216 00000000000000000000000010000000 vec($_, 0, 8) = 2 == 2 01000000000000000000000000000000 vec($_, 1, 8) = 2 == 512 00000000010000000000000000000000 vec($_, 2, 8) = 2 == 131072 00000000000000000100000000000000 vec($_, 3, 8) = 2 == 33554432 00000000000000000000000001000000 vec($_, 0, 8) = 4 == 4 00100000000000000000000000000000 vec($_, 1, 8) = 4 == 1024 00000000001000000000000000000000 vec($_, 2, 8) = 4 == 262144 00000000000000000010000000000000 vec($_, 3, 8) = 4 == 67108864 00000000000000000000000000100000 vec($_, 0, 8) = 8 == 8 00010000000000000000000000000000 vec($_, 1, 8) = 8 == 2048 00000000000100000000000000000000 vec($_, 2, 8) = 8 == 524288 00000000000000000001000000000000 vec($_, 3, 8) = 8 == 134217728 00000000000000000000000000010000 vec($_, 0, 8) = 16 == 16 00001000000000000000000000000000 vec($_, 1, 8) = 16 == 4096 00000000000010000000000000000000 vec($_, 2, 8) = 16 == 1048576 00000000000000000000100000000000 vec($_, 3, 8) = 16 == 268435456 00000000000000000000000000001000 vec($_, 0, 8) = 32 == 32 00000100000000000000000000000000 vec($_, 1, 8) = 32 == 8192 00000000000001000000000000000000 vec($_, 2, 8) = 32 == 2097152 00000000000000000000010000000000 vec($_, 3, 8) = 32 == 536870912 00000000000000000000000000000100 vec($_, 0, 8) = 64 == 64 00000010000000000000000000000000 vec($_, 1, 8) = 64 == 16384 00000000000000100000000000000000 vec($_, 2, 8) = 64 == 4194304 00000000000000000000001000000000 vec($_, 3, 8) = 64 == 1073741824 00000000000000000000000000000010 vec($_, 0, 8) = 128 == 128 00000001000000000000000000000000 vec($_, 1, 8) = 128 == 32768 00000000000000010000000000000000 vec($_, 2, 8) = 128 == 8388608 00000000000000000000000100000000 vec($_, 3, 8) = 128 == 2147483648 00000000000000000000000000000001
wait(2)
presente sul vostro sistema: aspetta che
un processo figlio termini e restituisce il pid del processo terminato oppure -1
se
non ci sono processi figli. Lo stato viene restituito in $?
. Va notato che un valore
restituito pari a -1
potrebbe significare che i processi figli sono stati raccolti
automaticamente, come descritto in the perlipc manpage.
-1
se tale processo non esiste. Su alcuni sistemi, un valore
0 indica che ci sono processi ancora in esecuzione. Lo stato viene restituito in $?
.
Se si afferma
use POSIX ":sys_wait_h"; #... do { $figlio = waitpid(-1, WNOHANG); } until $figlio > 0;
poi è possibile eseguire un wait non bloccante per tutti i processi zombi
pendenti. Il wait non bloccante è disponibile su elaboratori che supportano sia
la chiamata di sistema waitpid(2)
che quella wait4(2). Comunque, l'attendere per un
particolare pid con FLAG di 0
è implementato ovunque. (Il Perl emula la
chiamata di sistema ricordando i valori dello stato dei processi che sono usciti ma che
non sono stati ancora raccolti dallo script Perl).
Va notato che su alcuni sistemi, un valore restituito pari a -1
potrebbe significare che i
processi figli sono stati automaticamente raccolti. Consultate the perlipc manpage per i dettagli e
per altri esempi.
eval
si aspetta un valore di lista. Restituisce falso se il contesto si aspetta uno scalare.
Restituisce un valore indefinito se il contesto non si aspetta alcun valore (contesto
vuoto).
return unless defined wantarray; # non si disturbi facendo altro my @a = calcolo_complesso(); return wantarray ? @a : "@a";
Il risultato di wantarray()
è non specificato nello scope di livello
più esterno di un file, in un blocco BEGIN
, CHECK
, INIT
o END
oppure in un metodo
DESTROY
.
Piuttosto, questa funzione si sarebbe dovuta chiamare wantlist()
[``wantarray''=``voglio un array'' mentre ``wantlist''=``voglio una lista'', NdT].
Se LISTA è vuota e $@
contiene già un valore (solitamente derivante da
un precedente eval), tale valore viene utilizzato dopo aver concatenato "\t...caught"
[preso, NdT]
a $@
. Questo è utile per rimanere quasi, ma non del tutto, uguali a die
.
Se $@
è vuota, allora viene utilizzata la stringa
"Warning: Something's wrong"
[``Attenzione: Qualcosa è andato storto'', NdT].
Se è stato installato un handler di $SIG{__WARN__}
, non viene visualizzato
alcun messaggio. È compito dell'handler occuparsi del messaggio nella maniera che
ritene opportuna (ad esempio, convertendolo in una die
). La maggior parte degli
handler devono quindi occuparsi di visualizzare i warning che non sono preparati a
gestire, chiamando warn
di nuovo all'interno dell'handler stesso. Va notato che questa
è una procedure sicura, che non creerà un ciclo senza fine,
poiché gli hook a __WARN__
non vengono chiamati dall'interno di uno di essi.
Noterete che questo comportamento è in qualche modo diverso da quello degli
handler di $SIG{__DIE__}
(che non sopprimono il testo di errore, ma possono invece
chiamare di nuovo die
per cambiarli).
L'uso dell'handler __WARN__
fornisce un potente metodo per mettere a tacere tutti i
warning (anche quelli cosiddetti obbligatori). Ad esempio:
# cancella *tutti* i warning della compilazione BEGIN { $SIG{'__WARN__'} = sub { warn $_[0] if $FAIWARN } } my $pippo = 10; my $pippo = 20; # nessun warning sul my $pippo duplicato, # ma ehi, lo avete chiesto voi! # nessun warning di compilazione o esecuzione prima di questo punto $FAIWARN = 1;
# warning di esecuzione abilitati dopo questo punto warn "\$pippo e` vivo e $pippo!"; # viene mostrato
Consultate the perlvar manpage per dettagli sull'impostazione delle voci in %SIG
, e per altri
esempi. Consultate il modulo Carp per altri tipi di warning che usano le sue funzioni
carp()
e cluck().
select
) potrebbe essere impostato esplicitamente assegnando il nome del formato alla
variabile $~
.
L'elaborazione della parte superiore del modulo viene trattata automaticamente: se c'è
uno spazio insufficiente sulla pagina corrente per il record formattato, la pagina viene
avanzata scrivendo un form feed [avanzamento modulo, NdT], per formattare l'intestazione della
nuova pagina viene usato uno speciale formato sommità-della-pagina, poi il record viene
scritto. Di default, il formato sommità-della-pagina è il nome del filehandle a
cui è aggiunto ``_TOP'' [sommità, NdT], ma può essere dinamicamente
impostato al formato di propria scelta assegnando il nome alla variabile $^
mentre il
filehandle viene selezionato. Il numero di linee rimanenti sulla pagina corrente si trova nella
variabile $-
, la quale può essere impostata a 0
per forzare una nuova pagina.
Se FILEHANLDE non è specificato, l'output va sul canale di output di default corrente,
il quale comincia come STDOUT ma può essere cambiato dall'operatore select
. Se il
FILEHANDLE è una ESPR, allora l'espressione viene valutata e la stringa risultante
viene usata per cercare il nome del FILEHANDLE a tempo di esecuzione. Per dell'altro sui
formati, si veda the perlform manpage.
Va notato che write non è l'opposto di read
. Sfortunatamente.
tr///
. Consultate the perlop manpage.
La versione su cui si basa questa traduzione è ottenibile con:
perl -MPOD2::IT -e print_pod perlfunc
Per maggiori informazioni sul progetto di traduzione in italiano si veda http://pod2it.sourceforge.net/ .
Traduzione a cura di dree e molti altri.
Revisione a cura di dree.
NOME |