Uso confuso di & & e || operatori

stavo sfogliando un file /etc/rc.d/init.d/sendmail (so che non viene quasi mai utilizzato, ma io “m studiando per un esame), e sono diventato un po confuso riguardo agli operatori && e ||. Ho letto dove possono essere usati in affermazioni come:

if [ test1 ] && [ test2 ]; then echo "both tests are true" elif [ test1 ] || [ test2 ]; then echo "one test is true" fi 

Tuttavia, questo script mostra istruzioni a riga singola come:

[ -z "$SMQUEUE" ] && SMQUEUE="QUEUE" [ -f /usr/sbin/sendmail ] || exit 0 

Sembra che utilizzino gli operatori && e || per suscitare risposte basate su test, ma non sono riuscito a trovare la documentazione relativa a questo uso particolare di questi operatori. Qualcuno può spiegare cosa fanno in questo particolare contesto?

Rispondi

Il lato destro di && verrà valutato solo se lo stato di uscita del lato sinistro è zero (cioè vero). || è lopposto: valuterà il lato destro solo se lo stato di uscita del lato sinistro è diverso da zero (cioè falso).

Puoi considerare [ ... ] per essere un programma con un valore di ritorno. Se il test allinterno restituisce vero, restituisce zero; altrimenti restituisce un valore diverso da zero.

Esempi:

$ false && echo howdy! $ true && echo howdy! howdy! $ true || echo howdy! $ false || echo howdy! howdy! 

Note aggiuntive:

Se lo fai which [, potresti vedere che [ punta effettivamente a un programma! Di solito non è effettivamente quello che viene eseguito negli script, tuttavia; esegui type [ per vedere cosa viene effettivamente eseguito. Se vuoi provare a utilizzare il programma, specifica il percorso completo come quindi: /bin/[ 1 = 1.

Commenti

  • Quando vedi ” X o Y “, esegui il test di X. Se ‘ è vero, conosci già la risposta a ” X o Y ” (è ‘ è vero), quindi non è necessario testare Y. Se è ‘ è vero, non ‘ non conosci la risposta a ” X o Y “, quindi devi testare Y. Quando vedi ” X e Y ” , provi X. Se ‘ è falso, conosci già la risposta a ” X e Y ” (it ‘ s false), s o non è necessario testare Y. Se X è vero, è necessario testare Y per vedere se ” X e Y ” è true.
  • Invece di ” se il lato sinistro restituisce zero “, scriverei ” se lo stato di uscita del comando di sinistra ‘ è zero “. Trovo ” return ” un po ambiguo in quanto loutput e lo stato di uscita possono essere entrambi considerati ” valori restituiti ”
  • Non solo puoi ” considerare [ ... ] come programma “, in molti casi è . ‘ è comunemente nel file /bin/[ o /usr/bin/[.
  • I programmatori C troveranno questo super confuso. Lo 0 significa falso … Mentre in shellscripting 0 significa vero … Mente a bocca aperta.
  • @Calmarius Se ‘ sei abituato a C, pensa a return stati, non booleani, dove return 0 significa successo.

Risposta

Ecco il mio cheat sheet:

  • “A; B “Esegui A e poi B, indipendentemente dal successo di A
  • ” A & & B “Esegui B se A è riuscito
  • “A || B “Esegui B se A non è riuscito
  • ” A & “Esegui A in background.

Commenti

  • Ci sono ‘ alcuni interessanti paralleli lambda calculus in corso qui dimostrati nel funzionamento di JavaScript (definire le variabili in ordine); ” sinistra (noto anche come true) “: (a => b => a). ” right (aka false) “: (a => b => b). ” A; B ” ” quindi ” (a => b => (() => b())(a())). ” A & & B ” ” se senza altro (quando) ” (a => b => a()(() => right)(b)).” A || B ” ” else senza if (a meno che) ” (a => b => a()(b)(() => right)). ” a & & b || c ” ” ifThenElse ” (a => b => c => (unless(when(a)(b))(c))()) .
  • nota che in bash, la sinistra è analoga a 0 / stringa vuota, la destra analoga è tutto il resto.
  • Che ne dici di una singola barra verticale?

Risposta

per espandere la risposta di @ Shawn-j-Goff “dallalto, && è un AND logico e || è un OR logico.

Vedi questa parte del Guida avanzata allo scripting di Bash. Alcuni dei contenuti del collegamento per riferimento utente come di seguito.

& & AND

if [ $condition1 ] && [ $condition2 ] # Same as: if [ $condition1 -a $condition2 ] # Returns true if both condition1 and condition2 hold true... if [[ $condition1 && $condition2 ]] # Also works. # Note that && operator not permitted inside brackets #+ of [ ... ] construct. 

|| OPPURE

if [ $condition1 ] || [ $condition2 ] # Same as: if [ $condition1 -o $condition2 ] # Returns true if either condition1 or condition2 holds true... if [[ $condition1 || $condition2 ]] # Also works. # Note that || operator not permitted inside brackets #+ of a [ ... ] construct. 

Risposta

Dalla mia esperienza utilizzo & & d || per ridurre unistruzione if a una singola riga.

Supponiamo che stiamo cercando un file chiamato /root/Sample.txt allora literazione tradizionale sarebbe la seguente nella shell:

if [ -f /root/Sample.txt ] then echo "file found" else echo "file not found" fi 

Queste 6 righe possono essere ridotte a una singola riga:

[[ -f /root/Sample.txt ]] && echo "file found" || echo "file not found" 

Quando si eseguono alcune iterazioni per impostare variabili o per creare file ecc., la vita è più facile e lo script sembra più fluido usando la funzione if a riga singola, lunico inconveniente è che diventa un po più difficile implementare più comandi da una singola iterazione, tuttavia puoi usare le funzioni.

Commenti

  • È interessante. Mi ricorda il codice objc (a == b)? val = 1: val = 2;
  • Come posso utilizzare questo comando quando voglio eseguire un processo in background con ” & “? Ricevo un errore di sintassi per ./someScript.sh & && echo 'ok' || echo 'ko'
  • nel formato: foo && bar || baz, se foo riesce quindi bar fallisce, verrà eseguito baz, quindi è leggermente diverso da un if istruzione.
  • Devo notare che è possibile eseguire più comandi di seguito tra {} parentesi, utilizzando && o ||, ad esempio: pidof udpxy > /dev/null 2>&1 && echo "udpxy is up!" || { echo "udpxy is down!"; /etc/init.d/udpxy restart; }. Vale anche la pena ricordare che if..then..else è un ” riconoscimento ” più affidabile di true / condizioni false rispetto allutilizzo di && e ||.

Risposta

Esiste una nozione di “scorciatoia”.

Quando viene valutato (expr1 && expr2)expr2 viene valutato solo se exp1 restituisce” true “. Questo perché sia expr1 E expr2 devono essere veri affinché (expr1 && expr2) sia vero. Se expr1 restituisce “false” expr2 NON viene valutato (scorciatoia) perché (expr1 && expr2) è già “flase”.

Prova quanto segue: presumi che il file F1 esista & file F2 non esiste:

( [ -s F1 ] && echo "File Exists" ) # will print "File Exists" - no short cut ( [ -s F2 ] && echo "File Exists" ) # will NOT print "File Exists" - short cut

Allo stesso modo per || (o) – ma breve il taglio è invertito.

Commenti

  • La logica viene solitamente chiamata ” cortocircuito “. ‘ non ho mai visto la frase ” scorciatoia ” utilizzata. Lo menziono per aiutare a trovare riferimenti.

Risposta

Gli esempi nella risposta di Shawn J. Goff sono corrette, ma la spiegazione è il contrario. Controlla:

Il lato destro di & & verrà valutato solo se lo stato di uscita del lato sinistro è NONZERO. || è lopposto: valuterà il lato destro solo se lo stato di uscita del lato sinistro è ZERO.

Commenti

  • Sei consapevole che per le shell zero il codice di uscita restituisce vero e quindi il codice di uscita diverso da zero sul lato sinistro di && fa sì che lintera espressione restituisca false ?
  • Qualcuno non ha approvato le tue modifiche perché non era la tua risposta.Se pensi che una risposta sia sbagliata dovresti votarla negativamente ed eventualmente lasciare un commento; se pensi che sia necessaria una modifica, dovresti lasciare un commento. La modifica serve per correggere errori di grammatica, formattazione e ortografia che non cambiano il significato della risposta.
  • @countermode I ‘ scusa, hai ragione, Ho pensato che in Linux zero = falso e diverso da zero = vero (come in C e molti altri linguaggi / ambienti / piattaforme). Mi scuso per il malinteso.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *