Oggi parleremo della differenza tra vecchio "[" e nuovo "[["
Come ormai tutti sappiamo, "[" è il comando test e il suo compito è quello di valutare un'espressione tramite gli operatori logici. Basta digitare nel terminale
man test
oppure
man [
per capire meglio di cosa stiamo parlando.
[[ è la nuova versione del comando test (si fa per dire! è stato introdotto nel lontano 1998! :D). Badate, non è un nuovo comando, bensì un miglioramento del vecchio test.
Cerchiamo di coglierne alcune differenze sostanziali.
Partiamo dagli operatori < (minore) e > (maggiore)
#!/bin/bash
numero1=10
numero2=20
if [[ "$numero1" > "$numero2" ]]; then
echo "buongiorno"
else
echo "buonasera"
fi
exit 0
Proviamo, ora, a riscrivere lo stesso script, utilizzando però il vecchio test
#!/bin/bash
numero1=10
numero2=20
if [ "$numero1" > "$numero2" ]; then
echo "buongiorno"
else
echo "buonasera"
fi
exit 0
Avete notato qualcosa di strano? Ebbene sì, non vi riconosce il "maggiore" :D e vi stampa anche il file di testo di nome 20. La ragione è che nel vecchio test per avere l'operatore "maggiore" bisogna usare la seguente sintassi \>
Lo stesso discorso vale per < (minore)
sintetizzando
1 nel vecchio test: \< \>
2 nel nuovo test: < >
Vediamo un'altra differenza. AND e OR
Già sappiamo che, in uno script, OR e AND vengono indicati con -o (OR) e -a (AND), tuttavia possono essere indicati diversamente: && (AND) e || (OR).
Bene, l'altra differenza tra il vecchio e il nuovo comando test sta in questo
1. nel vecchio test [, come tutti sappiamo, OR e AND si scrivono rispettivamente "-o" e "-a"
2. nel nuovo test, invece, && (AND) e || (OR)
E se provassimo a scrivere nel nuovo test -o al posto di || ?
#!/bin/bash
a=5
c=2
if [[ $a -eq 5 -o $c -lt 3 ]]; then
echo "$a è uguale a 5"
echo "$c è minore di 3"
else
echo "$a non è uguale a 5"
echo "$c non è minore di 3"
fi
exit 0
Ottereste una serie di errori.
E se facessimo il contrario? Scrivere || al posto di -o nel vecchio test?
#!/bin/bash
a=5
c=2
if [ $a -eq 5 || $c -lt 3 ]; then
echo "$a è uguale a 5"
echo "$c è minore di 3"
else
echo "$a non è uguale a 5"
echo "$c non è minore di 3"
fi
exit 0
evidentemente l'if non funziona neanche in questo caso.
sintetizzando:
a. nel vecchio test "-a" e "-o"
b. nel nuovo test "&&" e "||"
Vediamo un'altra differenza
#!/bin/bash
miocane="dagor il terribile"
tuocane="termegisto il temerario"
if [ $tuocane = $miocane ]; then
echo "caspita, i nostri cani hanno lo stesso nome"
else
echo "il nome del mio cane è più bello"
fi
exit 0
Lanciando questo script, noterete che vi dà un errore: "troppi argomenti". Vai a dargli torto! La ragione, lo abbiamo detto anche nei post precedenti, è che in questi casi è necessario utilizzare i doppi apici. In questo modo:
#!/bin/bash
miocane="dagor il terribile"
tuocane="termegisto il temerario"
if [ "$tuocane" = "$miocane" ]; then
echo "caspita, i nostri cani hanno lo stesso nome"
else
echo "il nome del mio cane è più bello"
fi
exit 0
Nel nuovo test invece non avrebbe dato problemi, cioè neanche senza l'uso dei doppi apici. Provare per credere.
#!/bin/bash
miocane="dagor il terribile"
tuocane="termegisto il temerario"
if [[ $tuocane = $miocane ]]; then
echo "caspita, i nostri cani hanno lo stesso nome"
else
echo "il nome del mio cane è più bello"
fi
exit 0
La verità?
Nel vecchio test le variabili senza apici vengono espanse. Nel nostro caso avremo:
[ dagor il terribile = termegisto il temerario
come potete notare, i parametri crescono a dismisura; infatti ogni parola viene vista come un parametro. il vecchio test impazzisce perchè non riesce a trovare l'operatore e viene fuori l'errore.
Perchè ciò non succeda, è necessario usare i doppi apici. Cosa che nel nuovo test non è necessaria.
Facciamo un altro esempio. Confrontiamo due stringhe per vedere se sono uguali.
#!/bin/bash
a="aria autunnale"
if [ $a == "estate" ];then
echo "vero"
else
echo "falso"
exit 1
fi
Avviene, anche in questo caso, che la shell mi dà un errore. Il motivo, lo dico subito, è che non ho messo la viariabile $a tra i doppi apici.
vedete?
bit3lux@bit:~/Scrivania$ ./stagioni.sh
./stagioni.sh: line 5: [: too many arguments
Ma cerchiamo di vederci ancora più chiaro!
Come ormai sappiamo, o dovremmo sapere, usando gli apici doppi si conserva il valore letterale di tutti i caratteri, ad eccezione del segno del
dollaro.
Ciò premesso, facciamo il debug. Tranquilli, in un prossimo post se ne occuperà dettagliatamente Lightuono. Per ora, in modo approssimativo, diciamo che è un metodo per capire in cosa consiste l'errore segnalato dalla shell.
Poniamo che l'ultimo script lo abbiamo chiamato stagioni.sh
Per fare il debug devo digitare, al prompt della shell,
$ bash -x stagioni.sh
Vedete l'errore?
bit3lux@bit:~/Scrivania$ bash -x stagioni.sh
+ a='aria autunnale'
+ '[' aria autunnale == estate ']'
stagioni.sh: line 5: [: too many arguments
+ echo falso
falso
+ exit 1
Con il debug si tocca con mano il problema. Ci dice, infatti, che il confronto non viene fatto tra le due stringhe, ma tra [, aria, autunnale, ==, estate. Ecco perchè test impazzisce!
Il problema, anche in questo caso, si può risolvere in due modi:
1. usare il vecchio test e mettere la variabile tra i doppi apici
2. usare il nuovo test senza bisogno di mettere la variabile tra i doppi apici.
Con questo post finisce il capitolo sul costrutto IF; ma chiuso un capitolo se ne apre subito un altro: CASE!
Alla prossima
Io e Lightuono
Nessun commento:
Posta un commento