Förvirrande användning av & & och || operatörer

Jag skumade igenom en /etc/rc.d/init.d/sendmail -fil (jag vet att det nästan aldrig används, men jag ”m studerar för en tentamen) och jag har blivit lite förvirrad över operatörerna && och ||. Jag har läst var de kan användas i uttalanden som:

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

Detta skript visar emellertid enradiga uttalanden som:

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

De verkar använda operatörerna && och || för att framkalla svar baserat på test, men jag har inte kunnat gräva upp dokumentation om just denna användning av dessa operatörer. Kan någon förklara vad dessa gör i just detta sammanhang?

Svar

Höger sida av && utvärderas endast om utgångsstatusen för vänster sida är noll (dvs. sant). || är motsatsen: den kommer att utvärdera höger sida endast om statusen för vänster sida är noll (dvs. falsk).

Du kan överväga [ ... ] för att vara ett program med returvärde. Om testet inuti utvärderas till sant returnerar det noll; det returnerar i annat fall noll.

Exempel:

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

Extra anteckningar:

Om du gör which [, kanske du ser att [ faktiskt pekar på ett program! Det är dock vanligtvis inte det som körs i skript. Kör type [ för att se vad som faktiskt körs. Om du vill försöka använda programmet, ge bara hela vägen som så: /bin/[ 1 = 1.

Kommentarer

  • När du ser ” X eller Y ” testar du X. Om det ’ är sant, vet du redan svaret på ” X eller Y ” (det ’ är sant), så du behöver inte testa Y. Om det ’ sant, du vet inte ’ svaret på ” X eller Y ”, så du måste testa Y. När du ser ” X och Y ” testar du X. Om det ’ är falskt, vet du redan svaret på ” X och Y ” (it ’ s falskt), s o inget behov av att testa Y. Om X är sant, behöver du testa Y för att se om ” X och Y ” är true.
  • I stället för ” om vänster sida returnerar noll ” skulle jag skriva ” om kommandot till vänster ’ s utgångsstatus är noll ”. Jag tycker att ” returnerar ” lite tvetydigt eftersom både utgången och utgångsstatusen kan betraktas som ” returnerar värden ”
  • Inte bara kan du ” överväga [ ... ] för att vara ett program ”, i många fall är . Det ’ är vanligt i filen /bin/[ eller /usr/bin/[.
  • C-programmerare kommer att tycka att det här är superförvirrande. Där 0 betyder falsk … Medan i shellscripting betyder 0 betyder sant … Mind blown.
  • @Calmarius Om du ’ är van vid C, tänk på return statusar, inte booleaner, där return 0 betyder framgång.

Svar

Här är mitt fuskark:

  • ”A; B ”Kör A och sedan B, oavsett framgång för A
  • ” A & & B ”Kör B om A lyckades
  • ”A || B ”Kör B om A misslyckades
  • ” A & ”Kör A i bakgrunden.

Kommentarer

  • Det finns ’ några intressanta lambdakalkylparalleller som pågår här i JavaScript som fungerar (definiera variablerna i ordning); ” vänster (aka true) ”: (a => b => a). ” rätt (aka falsk) ”: (a => b => b). ” A; B ” ” sedan ” (a => b => (() => b())(a())). ” A & & B ” ” om utan annat (när) ” (a => b => a()(() => right)(b)).” A || B ” ” annat utan om (om inte) ” (a => b => a()(b)(() => right)). ” a & & b || c ” ” ifThenElse ” (a => b => c => (unless(when(a)(b))(c))()) .
  • Observera att i bash är vänster analog 0 / tom sträng, höger analog är allt annat.
  • Vad sägs om en enda vertikal stapel?

Svar

för att expandera på @ Shawn-j-Goffs svar från ovan, && är en logisk AND och || är en logisk ELLER.

Se denna del av Advanced Bash Scripting Guide. En del av innehållet från länken för användarreferens enligt nedan.

& & OCH

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. 

|| ELLER

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. 

Svar

Från min erfarenhet använder jag & & och d || för att minska ett if-uttalande till en enstaka rad.

Säg att vi letar efter en fil som heter /root/Sample.txt, då skulle den traditionella iterationen vara som följer i skal:

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

Dessa 6 rader kan reduceras till en enda rad:

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

När du kör några iterationer för att ställa in variabler eller för att skapa filer etc., livet är lättare och skriptet ser snyggare ut med funktionen en rad om det är den enda nackdelen att det blir lite svårare att implementera flera kommandon från en enda iteration men du kan använda funktioner.

Kommentarer

  • Det här är coolt. Påminner mig om objc-kod (a == b)? val = 1: val = 2;
  • Hur kan jag använda det här kommandot när jag vill köra en process i bakgrunden med ” & ”? Jag får ett syntaxfel för ./someScript.sh & && echo 'ok' || echo 'ko'
  • I form: foo && bar || baz, om foo lyckas då bar misslyckas, baz körs, så det skiljer sig subtilt från en if uttalande.
  • Jag måste notera att det är möjligt att utföra flera kommandon i rad i {} parenteser med && eller ||, såsom: pidof udpxy > /dev/null 2>&1 && echo "udpxy is up!" || { echo "udpxy is down!"; /etc/init.d/udpxy restart; }. Det är också värt att nämna att if..then..else är en mer tillförlitlig ” igenkännare ” av true / falska villkor än att använda && och ||.

Svar

Det finns en uppfattning om ”genväg”.

När (expr1 && expr2) utvärderas – expr2 utvärderas endast om exp1 utvärderas till” true ”. Detta beror på att både expr1 OCH expr2 måste vara sanna för att (expr1 && expr2) ska vara sant. Om expr1 utvärderas till ”falskt” utvärderas expr2 (genväg) eftersom (expr1 && expr2) är redan ”flase”.

Prova följande – anta att fil F1 finns & fil F2 finns inte:

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

På samma sätt för || (eller) – men kort skärning är omvänd.

Kommentarer

  • Logiken kallas vanligtvis ” kortslutning ”. Jag ’ Jag har aldrig sett frasen ” genväg ” används. Jag nämner detta för att hjälpa till med att hitta referenser.

Svar

Exemplen i svaret av Shawn J. Goff är korrekta, men förklaringen är tvärtom. Kontrollera:

Höger sida av & & utvärderas endast om utgångsstatusen till vänster är NONZERO. || är motsatsen: den utvärderar bara höger sida om statusen för vänster sida är NOLL.

Kommentarer

  • Du är medveten om att för skal noll utgångskod utvärderas till sant och därmed icke-noll utgångskod till vänster om && resulterar i att hela uttrycket returnerar falskt ?
  • Någon godkände inte dina ändringar eftersom det inte var ditt svar.Om du tycker att något svar är felaktigt bör du nedrösta det och eventuellt lämna en kommentar; om du tror att det kräver en ändring, bör du lämna en kommentar. Redigering är för att korrigera grammatik, formatering och stavfel som inte ändrar innebörden av svaret.
  • @countermode I ’ tyvärr, du har rätt, Jag tänkte i Linux zero = false och nonzero = true (som i C och många andra språk / miljöer / plattformar). Jag ber om ursäkt för missförståndet.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *