Sembrano entrambi segnalare a BASH di iniziare con un altro comando seguendo i simboli, ma c'è una netta differenza?
Sembrano entrambi segnalare a BASH di iniziare con un altro comando seguendo i simboli, ma c'è una netta differenza?
Risposte:
Con questa linea:
command1 && command2
command2 verrà eseguito se (e solo se) command1 restituisce lo stato di uscita zero, mentre in questa riga:
command1 ; command2
sia command1 che command2 verranno eseguiti indipendentemente. Il punto e virgola consente di digitare molti comandi su una riga.
Puoi provare la differenza per te:
ls /invalid/path && echo "hello!"
poiché / invalid / percorso non esiste, non possiamo mostrarti l'elenco delle directory. Non funzionerà con un messaggio di errore: "ls: / invalid / path: nessun file o directory".
La seconda metà del comando (echo "ciao!") Non viene mai nemmeno eseguita perché la prima metà non è riuscita.
ls /invalid/path ; echo "hello!"
Lo stesso messaggio di errore appare come prima, ma questa volta viene eseguita la seconda parte !
ls: / invalid / path: nessun file o directory simile
ciao!
Perché è utile?
Supponiamo di voler estrarre un file chiamato archive.tar.gz.
Puoi usare il comando tar zxvf archive.tar.gz && rm archive.tar.gz
.
Se per qualsiasi motivo l'estrazione dell'archivio fallisce, la seconda parte non viene eseguita! Puoi riprovare.
Se usi; nella stessa situazione, l'archivio viene eliminato e non puoi riprovare.
&&
è AND
, il che significa che il secondo comando verrà eseguito solo se il primo ha restituito true (nessun errore).
AND
esecuzione il secondo parametro diventa irrilevante se il primo è uguale false
e quindi il codice sottostante viene ottimizzato per rimandare la valutazione del secondo parametro fino a quando non sa quale sia il primo.
&&
è solo un operatore binario, una funzione. L'unica cosa "speciale" è che si tratta della notazione infix (che è comunque standard per la maggior parte di questo tipo di operatori) e dell'esecuzione ritardata del secondo operando. Che l'esecuzione ritardata anzi gli dà la possibilità di essere utilizzato come qualcosa che può essere considerato concettualmente come un if
dichiarazione in questo contesto , ma ciò non toglie nulla al fatto che è originariamente destinato utilizzo è entro il condizionale di un vero e proprio if
comunicato. L'uso qui è davvero più di un "hack".
a && b || c = (a && b) || c
. Ordine di valutazione semplice. Non c'è davvero nessun mistero lì. Se le scrivessi come le tue funzioni tipiche, sembrerebbe semplicemente or(and(a, b), c)
. Questa logica è la stessa in un if
condizionale e quando la immette direttamente nella riga di comando perché &&
e ||
sono operatori , prendono due operandi e ne restituiscono un altro.
Aggiornamento : ho aggiunto come script per evidenziare alcune delle possibili trappole:
Perché nessun altro ha menzionato "||", lo farò
Aggiornamento2 : alcune importanti riformulazioni qui
&& sono come una "allora" di un'istruzione "if" che risponde a "vero"
|| NON è come l '"altro" di una "se" affermazione ..
|| è come un "allora" di un'istruzione "if" che risponde a "falso"
Più specificamente, && mette alla prova $? restituisce il valore dell'ultima istruzione eseguita più di recente e passa il controllo all'istruzione o alla sotto-shell immediatamente dopo il && ... passa il controllo solo se $? è vero.
|| è simile e si vede spesso dopo un'istruzione &&, ma verifica un valore di ritorno falso ($?) dall'istruzione precedente eseguita più di recente ... NB! , Nota Bene! Nota bene! .... se l'istruzione predecing è un'istruzione && che si ripete falsa quando ti aspetti che sia vera, allora || risponderà al falso, quindi mescolare entrambi sulla stessa linea potrebbe essere rischioso
Il punto principale che sto cercando di fare è in relazione a un errore che ho fatto. cioè:
## [[condizione]] && A || B
è non non si comporta come un C / C ++ ternario stile. cioè:
// (condizione)? A: B
Vedi lo script qui sotto per esempi di risultati "imprevisti" da "A"
Il test di base e && e il || L'istruzione deve essere tutta sulla stessa riga ...
Esegui questo script per vedere dove le cose possono andare storte quando si usano && e ||
L' istruzione eseguita più di recente potrebbe non essere quella che ti aspetti.
[[condizione]] && echo Ciao || echo Arrivederci .... è generalmente sicuro,
perché un'eco ben formata tornerà vera.
ma per quanto riguarda l'accesso a un file che non esce?
#!/bin/bash
#
# "as expected" return codes" means: expected to behave like a normal AND / OR contition test
#
if [[ "$1" != "" ]] ; then exit $1; fi # recursive call to return an arbitary $? value (decimal)
echo
echo 'test 1: All return codes are "as expected"'
echo ======
((1==1)) && echo " ((1==1)) rc=$? ..&&.. condition is true" || echo " ((1==1)) rc=$? ..||.. condition is false"
$0 0 && echo " \$0 0 rc=$? ..&&.. condition is true" || echo " \$0 0 rc=$? ..||.. condition is false"
((1!=1)) && echo " ((1!=1)) rc=$? ..&&.. condition is true" || echo " ((1!=1)) rc=$? ..||.. condition is false"
$0 1 && echo " \$0 1 rc=$? ..&&.. condition is true" || echo " \$0 1 rc=$? ..||.. condition is false"
echo
echo 'test 2: Now throw in some "unexpected" errors into the first of the &&/|| pair'
echo ======
((1==1)) && (echo " ((1==1)) rc=$? ..&&.. condition is true"; $0 1) || echo " ((1==1)) rc=$? ..||.. condition is false"
$0 0 && (echo " \$0 0 rc=$? ..&&.. condition is true"; $0 2) || echo " \$0 0 rc=$? ..||.. condition is false"
((1!=1)) && (echo " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3) || echo " ((1!=1)) rc=$? ..||.. condition is false"
$0 1 && (echo " \$0 1 rc=$? ..&&.. condition is true"; $0 4) || echo " \$0 1 rc=$? ..||.. condition is false"
echo
echo 'test 3: Now swap the order of && and || statements, using "as expected" return codes'
echo ======
((1==1)) || echo " ((1==1)) rc=$? ..||.. condition is true" && echo " ((1==1)) rc=$? ..&&.. condition is false"
$0 0 || echo " \$0 0 rc=$? ..||.. condition is true" && echo " \$0 0 rc=$? ..&&.. condition is false"
((1!=1)) || echo " ((1!=1)) rc=$? ..||.. condition is true" && echo " ((1!=1)) rc=$? ..&&.. condition is false"
$0 1 || echo " \$0 1 rc=$? ..||.. condition is true" && echo " \$0 1 rc=$? ..&&.. condition is false"
echo
echo 'test 4: With the order of && and || statements still swapped, introduce "unexpected" errors into the first of the &&/|| pair'
echo ======
((1==1)) && (echo " ((1==1)) rc=$? ..&&.. condition is true"; $0 1) || echo " ((1==1)) rc=$? ..||.. condition is false"
$0 0 && (echo " \$0 0 rc=$? ..&&.. condition is true"; $0 2) || echo " \$0 0 rc=$? ..||.. condition is false"
((1!=1)) && (echo " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3) || echo " ((1!=1)) rc=$? ..||.. condition is false"
$0 1 && (echo " \$0 1 rc=$? ..&&.. condition is true"; $0 4) || echo " \$0 1 rc=$? ..||.. condition is false"
exit
provare
falso && echo "ciao"
e
falso; echo "ciao"
vedi la differenza
Il comando (funzione, nel caso di uno script) dopo &&
viene eseguito in base alla RETVAL del primo comando (funzione, nel caso di uno script). Forza il primo comando a restituire un valore pari a 0, se ha esito positivo. Possiamo verificare il valore restituito per eseguire ulteriori comandi.