Penso che la raccomandazione che hai visto fosse per POSIX sh e / o il testcomando che funge anche da [comando, piuttosto che il [[costrutto che è apparso in ksh (grazie a Stéphane Chazelas per la punta) ed è usato anche per esempio in bash, zsh e altri conchiglie.
Nella maggior parte dei linguaggi, come C, quando una clausola è già nota per essere vera o falsa, non è necessario valutare le parti rimanenti a seconda dell'operazione: se vero non dopo un logico o seguirlo, se falso non dopo un logico e , ecc. Questo ovviamente permette ad esempio di fermarsi quando un puntatore è NULL e non provare a dereferenziarlo nella clausola successiva.
Ma il costrutto di sh[ expr1 -o expr2 ] (inclusa l'implementazione di bash) non lo fa: valuta sempre entrambe le parti, quando si vorrebbe valutare solo expr1 . Ciò potrebbe essere stato fatto per compatibilità con l' testimplementazione del comando. D'altra parte, sh ||e &&segue il solito principio: non valutato se non cambierà il risultato.
Quindi la differenza da notare sarebbe:
: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
che produce:
true
or-was-evaluated
Sopra, ognuno [avrebbe potuto essere sostituito con il /usr/bin/[quale è un alias del testcomando, usato prima che [fosse incorporato nelle shell.
Mentre i due successivi costrutti:
: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
o
: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect
Produrrà truee lascerà solo effectvuoto: ||si comporta correttamente e ha [[corretto anche questo problema.
AGGIORNARE:
Come ha commentato @ StéphaneChazelas, ho perso diverse differenze relative alla domanda iniziale. Metterò qui solo il più importante (almeno per me): priorità degli operatori.
Mentre la shell non considererà la precedenza:
if true || true && false; then
echo true
else
echo false
fi
rese (perché non c'è precedenza e quindi prima true || trueviene valutata, quindi && false):
false
all'interno [[ ]]del &&operatore ha la precedenza sul ||:
if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi
rendimenti (perché 1 -eq 1 && 1 -eq 0è raggruppato ed è quindi il 2 ° membro di ||):
true
almeno per ksh , bash , zsh .
Quindi [[ ]]ha migliorato il comportamento su entrambi [ ]gli operatori logici diretti e shell.
[oppuretest( non[[), cercare iOBtag (collegati alla definizione "obsolescente") nelle specifiche POSIX pertest. Intest, ci sono alcuni casi patologici in cui può essere impossibile dire se(o)si intende che la sintassi sia significativa per il comando test o una stringa da testare, quindi le persone che ignorano i marcatori di obsolescenza e usano quella sintassi possono effettivamente aver bisogno del contrario-"x$foo"pratica obsoleta ; con[[, questo non è un problema.