L'espressione condizionale if
è
disponibile in entrambe le shell, ma con una diversa sintassi.
if
condizione1
then
lista di comandi secondizione1
è vera (true) [elif
condizione2
then
lista di comandi secondizione2
è vera (true)] [else
lista di comandi secondizione1
è falsa (false)]fi
Le condizioni sono sottoposte usualmente al comando test(1) o
[]
(Vedere la sezione 9.9.6).
L'if
e then
devono essere
separati con un newline o un punto e virgola (;).
#!/bin/sh if [ $# -ge 2 ] then echo $2 elif [ $# -eq 1 ]; then echo $1 else echo Nessun input fi
Sono richiesti degli spazi nel formato della condizione di
test(1), uno dopo [
e uno prima di
]
. Questo script potrebbe comportarsi in modo
differente a seconda che ci siano zero, uno o più argomenti su
linea di comando. Iniziando con nessun argomento:
$ ./if.sh
Nessun input
Ora con un argomento:
$ ./if.sh one
one
E ora con due argomenti:
$ ./if.sh one two
two
if
(condizione
)comando
-oppure-if
(condizione1
)then
lista di comandi secondizione1
è vera (true) [else
if
(condizione2
)then
lista di comandi secondizione2
è vera (true)] [else
lista di comandi secondizione1
è falsa (false)]endif
L'if
e then
devono stare
sulla stessa linea.
#!/bin/csh -f if ( $#argv >= 2 ) then echo $2 else if ( $#argv == 1 ) then echo $1 else echo Nessun input endif
Di nuovo, questo script potrebbe comportarsi in modo differente a seconda che ci siano zero, uno o più argomenti su linea di comando. Iniziando con nessun argomento:
%
./if.csh
Nessun input
Ora con un argomento:
%
./if.csh one
one
E ora con due argomenti:
%
./if.csh one two
two
Per scegliere tra una serie di valori di tipo stringa relativi a un
parametro si usa case
nella shell Bourne e
switch
nella shell C.
case
parametro
in
schema1
[|schema1a
])lista1 di comandi
;;schema2
)lista2 di comandi
lista2a di comandi
;;schema3
)lista3 di comandi
;; *) ;;esac
Si possono usare validi nomi di file meta-caratteri all'interno dello schema per il confronto. I ;; concludono ogni scelta e possono essere sulla stessa linea della scelta o a seguito di un newline, dopo l'ultimo comando per la scelta. Schemi alternativi per la scelta di un particolare caso sono separati da una barra verticale |, come nel primo schema dell'esempio precedente. I simboli wild card ,? per indicare un generico carattere e * per far corrispondere alcuni caratteri, possono essere usati singolarmente o in modo adiacente per completare stringhe.
Questo semplice esempio illustra come usare l'espressione
condizionale case
.
#!/bin/sh case $1 in aa|ab) echo A ;; b?) echo "B \c" echo $1;; c*) echo C;; *) echo D;; esac
Quindi quando si esegue lo script con l'argomento posto sulla colonna di sinistra, lo script risponde come sulla colonna di destra:
aa | A |
ab | A |
ac | D |
bb | B bb |
bbb | D |
c | C |
cc | C |
fff | D |
switch
(parametro
)case
schema1
:lista1 di comandi
[breaksw
]case
schema2
:lista2 di comandi
[breaksw
]default
: lista di comandi per il comportamento di default [breaksw
]endsw
breaksw
è opzionale e può essere
usato per interrompere lo switch dopo che si è verificata una
corrispondenza del valore di tipo stringa del parametro confrontato.
Switch
non accetta | nella lista degli schemi, ma
permette di unire insieme diverse strutture case
per fornire un simile risultato. Il seguente script di shell C ha lo
stesso comportamento dell'esempio precedente, riferito al
case
della shell Bourne.
#!/bin/csh -f switch ($1) case aa: case ab: echo A breaksw case b?: echo -n "B " echo $1 breaksw case c*: echo C breaksw default: echo D endsw
Per effettuare un ciclo tra una lista di valori di tipo
stringa si possono usare i comandi for
e
foreach
.
for
variabile
[in
lista_di_valori
]do
lista di comandi
done
La lista_di_valori
è opzionale,
presupponendo $@
se nulla viene specificato. Ogni
valore in questa lista viene sostituito sequenzialmente in
variabile
fino a quando la lista risulta
vuota. Possono essere usati wild card, che vengono applicati ai
nomi dei file nella directory corrente. Di seguito si illustra il
ciclo for
che copia tutti i file che finiscono con
.old
negli stessi nomi che finiscono però
con .new
. In questi esempi l'utility
basename(1) estrae la parte base del nome affinchè
si possa modificarne l'estensione.
#!/bin/sh for file in *.old do newf=`basename $file .old` cp $file $newf.new done
Il comando while
permette di effettuare il ciclo
sempre che la condizione sia vera.
while
condizione
do
lista di comandi
[break
] [continue
]done
Un semplice script per illustrare il ciclo
while
è:
#!/bin/sh while [ $# -gt 0 ] do echo $1 shift done
Questo script prende la lista degli argomenti, ne visualizza il primo, quindi effettua uno shift nella lista verso sinistra, perdendo il primo elemento originale. Il ciclo viene ripetuto fino a quando tutti gli argomenti sono stati spostati fuori dalla lista.
$ ./while.sh one two three
one
two
three
Questo costrutto di ciclo è solamente disponibile per la shell Bourne.
until
condizione
do
lista di comandi se la condizione è falsadone
La condizione viene verificata all'inizio di ogni ciclo e il ciclo termina quando la condizione è vera.
Uno script equivalente all'esempio del while
precedente è:
#!/bin/sh until [ $# -le 0 ] do echo $1 shift done
Si noti che qui si verifica per minore o
uguale, piuttosto che per maggiore,
poichè il ciclo until
viene abilitato da una
condizione falsa.
Sia il ciclo until
che il
while
sono solamente eseguiti se la condizione
è soddisfatta. La condizione viene valutata prima
dell'esecuzione dei comandi.
Le espressioni condizionali vengono valutate per valori
veri o falsi. Questo, di
solito, viene realizzato con test(1) o equivalentemente con i suoi
operatori []
. Se la condizione viene valutata vera,
viene settato uno stato di uscita zero (TRUE),
altrimenti viene settato uno stato di uscita non-zero
(FALSE). Se non ci sono argomenti viene settato
uno stato di uscita non-zero. Gli operatori utilizzati nelle
espressioni condizionali della shell Bourne sono mostrati qui
sotto.
Per i nomi di file le opzioni per test(1) sono date con la sintassi seguente:
-
opzione
filename
Le opzioni di test(1) disponibili per i file includono:
-r | vero se il file esiste ed è leggibile |
-w | vero se il file esiste ed è scrivibile |
-x | vero se il file esiste ed è eseguibile |
-f | vero se il file esiste ed è un file regolare (o per csh(1) esiste e non è una directory) |
-d | vero se il file esiste ed è una directory |
-h o -L | vero se il file esiste ed è un link simbolico |
-c | vero se il file esiste ed è un file speciale a caratteri (ad esempio un dispositivo al quale si accede un carattere alla volta) |
-b | vero se il file esiste ed è un file speciale a blocchi (ad esempio un dispositivo al quale si accede in blocchi di dati) |
-p | vero se il file esiste ed è un file pipe (fifo) |
-u | vero se il file esiste ed è setuid (ad esempio ha il bit set-user-id settato a s o S nel terzo bit) |
-g | vero se il file esiste ed è setgid (ad esempio ha il bit set-group-id settato a s o S nel sesto bit) |
-k | vero se il file esiste e ha lo sticky bit settato (una t nel nono bit) |
-s | vero se il file esiste ed ha una dimensione maggiore di zero |
C'è un test per i descrittori di file:
-t
[ | vero se l'aperto descrittore del file specificato (1, stdout(4), di default) è associato ad un terminale |
Ci sono test per le stringhe:
-z
| vero se la lunghezza della stringa è zero |
-n
| vero se la lunghezza della stringa non è zero |
| vero se stringa1 è
identica a stringa2 |
| vero se stringa1 non è
identica a stringa2 |
stringa | vero se la stringa non è nulla |
Ci sono dei confronti per gli interi:
| vero se gli interi n1 e
n2 sono uguali |
| vero se gli interi n1 e
n2 non sono uguali |
| vero se l'intero n1 è
maggiore dell'intero n2 |
| vero se l'intero n1 è
maggiore o uguale dell'intero
n2 |
| vero se l'intero n1 è
minore dell'intero n2 |
| vero se l'intero n1 è
minore o uguale dell'intero
n2 |
Sono disponibili i seguenti operatori logici:
! | negazione (unaria) |
-a | and (binario) |
-o | or (binario) |
() | le espressioni all'interno di ( ) vengono raggruppate insieme. Può essere necessario quotare le parentesi ( ) per impedire alla shell di interpretarle. |
La shell C possiede un suo set di operatori logici e relazionali built-in. In ordine decrescente di priorità questi sono:
(...) | raggruppa espressioni con ( ) |
~ | inverso (il suo complemento) |
! | negazione logica |
*, /, % | moltiplicazione, divisione, modulo |
+, - | addizione, sottrazione |
<<, >> | shift a sinistra di bit, shift a destra di bit |
<= | minore o uguale |
>= | maggiore o uguale |
< | minore |
> | maggiore |
= = | uguale |
!= | non uguale |
=~ | uguale a stringa |
!~ | non uguale a stringa |
& | AND bit |
^ | XOR bit (or esclusivo) |
| | OR bit |
&& | AND logico |
|| | OR logico |
{comando} | vero (1) se il comando termina con uno stato di uscita 0, falso (0) altrimenti. |
Inoltre la shell C permette richieste sul tipo e sui permessi dei file con gli operatori seguenti:
-r | ritorna vero (1) se il file esiste ed è leggibile, altrimenti ritorna falso (0) |
-w | vero se il file esiste ed è scrivibile |
-x | vero se il file esiste ed è eseguibile |
-f | vero se il file esiste e non è una directory |
-d | vero se il file esiste ed è una directory |
-e | vero se il file esiste |
-o | vero se l'utente corrente è il proprietario del file |
-z | vero se il file ha una lunghezza zero (file vuoto) |
Questo, ed altri documenti, possono essere scaricati da ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/
Per domande su FreeBSD, leggi la
documentazione prima di contattare
<questions@FreeBSD.org>.
Per domande su questa documentazione, invia una e-mail a
<doc@FreeBSD.org>.