C'è una differenza tra '&&' e ';' simboli in un terminale BASH standard?


57

Sembrano entrambi segnalare a BASH di iniziare con un altro comando seguendo i simboli, ma c'è una netta differenza?

Risposte:


76

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.


1
Interessante! Pensavo potesse essere solo un modo più comodo. Grazie!

42

Puoi provare la differenza per te:

  1. 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.

  2. 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.


8

&&è AND, il che significa che il secondo comando verrà eseguito solo se il primo ha restituito true (nessun errore).


1
&& è un "allora" (non un "e") ... vedi la mia risposta
Peter.O

2
@fred Direi che è un "e" con valutazione del corto circuito - se la prima parte è non vera, sa che il risultato totale deve essere falso, quindi salta la seconda parte. Ma concorda sul fatto che pensarlo come un "allora" raramente fa molta differenza in questo contesto.
jg-faustus,

2
@fred Anche se concettualmente potrebbe essere più semplice capirlo in questo modo, non sono d'accordo con la tua affermazione. L'idea è semplicemente che con qualsiasi AND esecuzione il secondo parametro diventa irrilevante se il primo è uguale falsee quindi il codice sottostante viene ottimizzato per rimandare la valutazione del secondo parametro fino a quando non sa quale sia il primo.
Ward Muylaert,

2
@fred Non sono sicuro di quale punto questo esempio stia cercando di fare. &&è 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 ifdichiarazione in questo contesto , ma ciò non toglie nulla al fatto che è originariamente destinato utilizzo è entro il condizionale di un vero e proprio ifcomunicato. L'uso qui è davvero più di un "hack".
Ward Muylaert,

3
@fred Naturalmente non è un operatore ternario, è solo la successione di due operazioni 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 ifcondizionale e quando la immette direttamente nella riga di comando perché &&e ||sono operatori , prendono due operandi e ne restituiscono un altro.
Ward Muylaert,

8

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 


1

provare

falso && echo "ciao"

e

falso; echo "ciao"

vedi la differenza


0

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.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.