L'espressione condizionale if è disponibile in entrambe le shell, ma con una diversa sintassi.
if condizione1 then lista di comandi se condizione1 è vera (true) [elif condizione2 then lista di comandi se condizione2 è vera (true)] [else lista di comandi se condizione1 è 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 se condizione1 è vera (true) [else if (condizione2) then lista di comandi se condizione2 è vera (true)] [else lista di comandi se condizione1 è 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:
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
foreach variabile (lista_di_valori) lista di comandi end
L'equivalente script in shell C per copiare tutti i file con estensione .old negli stessi file con estensione .new è:
#!/bin/csh -f foreach file (*.old) set newf = `basename $file .old` cp $file $newf.new end
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
while (condizione) lista di comandi [break] [continue] end
Se si vuole che la condizione sia sempre vera si specifica 1 all'interno del test condizionale.
Lo script di shell C equivalente a quello precedente è:
#!/bin/csh -f while ($#argv != 0 ) echo $argv[1] shift end
Questo costrutto di ciclo è solamente disponibile per la shell Bourne.
until condizione do lista di comandi se la condizione è falsa done
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 [descrittore_file] |
vero se l'aperto descrittore del file specificato (1, stdout(4), di default) è associato ad un terminale |
Ci sono test per le stringhe:
-z stringa |
vero se la lunghezza della stringa è zero |
-n stringa |
vero se la lunghezza della stringa non è zero |
stringa1 = stringa2 |
vero se stringa1 è identica a stringa2 |
stringa1 != stringa2 |
vero se stringa1 non è identica a stringa2 |
stringa | vero se la stringa non è nulla |
Ci sono dei confronti per gli interi:
n1 -eq n2 |
vero se gli interi n1 e n2 sono uguali |
n1 -ne n2 |
vero se gli interi n1 e n2 non sono uguali |
n1 -gt n2 |
vero se l'intero n1 è maggiore dell'intero n2 |
n1 -ge n2 |
vero se l'intero n1 è maggiore o uguale dell'intero n2 |
n1 -lt n2 |
vero se l'intero n1 è minore dell'intero n2 |
n1 -le n2 |
vero se l'intero n1 è minore o uguale dell'intero n2 |
Sono disponibili i seguenti operatori logici:
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 <[email protected]>.
Per domande su questa documentazione, invia una e-mail a <[email protected]>.