Förstå booleska operatörer i bash-skript [duplikat]

<åt sidan class = "s-notice s-notice__info js-post-notice mb16" role = "status" >

Denna fråga har redan svar här :

Svar

Variabeln $phone_missing är en sträng som råkar innehålla false. Och en icke-tom sträng utvärderas till true. Se även http://www.linuxintro.org/wiki/Babe#empty_strings

Kommentarer

  • Ah okej. Jag skulle ha förklarat den variabeln som boolesk (åtminstone inte med deklarera ordet) men askkonsolen vann inte '. Jag vill inte ' inte jämföra strängar. Hur görs detta rätt?
  • stackoverflow.com/questions/2953646/… , men var försiktig: den här killen KÖRER en strängvariabel och lika falskt som sant är unix-kommandon.

Svar

Jag använder ofta ”true” och ”false” eftersom de också är kommandon som bara återvänder till framgång respektive misslyckande. Då kan du göra

if "$phone_missing"; then ... 

Svar

Här är ett sätt att göra detta, samtidigt som de sanna / falska värdena behålls.

 phone_missing=false if [ "$phone_missing" != false ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi if [ "$phone_missing" == true ]; then echo "phone_missing is true." fi  

Dubbelcitaten runt $phone_missing är att skydda mot fallet där variabel phone_missing inte definieras alls. Ett annat vanligt idiom att avvärja mot detta är [ x$phone_missing != xfalse ], men citaten verkar mer naturliga för mig.

Tipsen finns i bash hjälpsidan för test:

 STRING True if string is not empty. ... ! EXPR True if expr is false. 

Så i princip kommer [ $foo ] att vara sant om $foo inte är tom. Inte sant eller falskt, bara icke-tomt. [ ! $foo ] är sant om $ foo är tomt eller odefinierat.

Du kan alltid ändra din kod för att bara ställa in phone_missing till en icke -vänligt värde e, vilket kommer att beteckna sant. Om phone_missing inte är inställt (eller tomt – phone_missing="") blir det falskt. Annars bör du använda strängtestoperatorerna (= och !=).

Det andra lilla problemet är uppgiften. Du har det som $phone_missing=true, medan det ska vara phone_missing=true (inget dollartecken).

Ledsen om det här är lite tät, det beror på att jag är. Det har varit en lång dag. 🙂

Svar

Andra svar gav dig en lösning, men jag kommer att förklara vad som var fel med det ursprungliga tänkandet.

Bash-variabler har inte typer, så det finns inget sådant som en boolesk variabel eller värde som sant eller falskt. I grund och botten är alla bash-variabler bara strängar.

När du testar en variabel / sträng i bash utan att ange typ av test (-n eller -z), det är som standard ett -n (icke-noll längdsträng) test.

[ "$var" ] motsvarar [ -n "$var" ]. Så länge som $var innehåller minst ett tecken, utvärderades det till sant.

Eftersom du förnekade uttrycket, [ ! "$var" ] motsvarar [ ! -n "$var" ]. Så om $var innehåller minst ett tecken är uttrycket falskt.

Eftersom false (vilket är en sträng) innehåller 5 tecken, uttrycket är falskt. Om det inte spelar någon roll vilken sträng du ställer in phone_missing till (true, 0, 1), kommer uttrycket alltid att vara false för att phone_missing inte är noll. Det enda sättet att göra det true är phone_missing="" eftersom det är noll längd.

Svar

Använd inte sträng för boolean. Använd heltal.

Ingång:

val=1 ((val)) && echo "true" || echo "false" val=0 ((val)) && echo "true" || echo "false" 

Output:

true false 

Källa :

((uttryck))

Uttrycket utvärderas enligt reglerna som beskrivs nedan under ARITMETISK EVALUERING. Om uttryckets värde inte är noll är returstatus 0; annars är returstatus 1. Detta motsvarar exakt låt ”uttryck”.

Svar

Jag skulle ha gjort detta som en kommentar för att stödja James Ko men hade inte rep att kommentera eller rösta offentligt.

Frågan här är att [] parenteserna är en indikation för att göra ett jämförelsetest som värde eller stränglikhet.

Sträng sanning i bash för en tom sträng är "" (tom sträng) utvärderas till falsk (returvärde 1) och alla icke tomma strängar ”falska” ”sanna ”eller” bob ”s din farbror” utvärderas till sant (returvärde 0).

Du kan bevisa detta för dig själv med:

 if [ "foo" ]; then echo true is $?; else echo false is $?; fi 

$? ovan är en speciell variabel som innehåller de sista kommandona exit status (0 framgång och alla> 0 för felkod) och kommer att mata ut true is 0. Du kan ersätta "foo" med vad du vill och resultatet blir detsamma förutom om du ersätter det med en tom sträng "" eller "" i vilket fall den utvärderar det andra tillståndet och matar ut false is 1.

När du använder [ ] parenteser det interna uttalandet som! $ phone_missing utvärderas och returnerar sedan ett 0 för true eller 1 för falskt till if-kontot Jag uttalar mig. Eftersom parentesen utvärderar sträng- och värdejämförelser utvidgas $ phone_missing först till den icke tomma strängen ”false” som utvärderas av [] som icke tom sträng (eller true) och sedan! inverterar resultatet vilket resulterar i att if-uttalandet får ett falskt (eller returvärde 1) och det hoppar över den villkorliga kroppen som utför det andra uttalandet om det finns.

Som James Ko sa skulle notationen vara att bara passera variabel som håller din ”boolean” till if-kontrolluttrycket. Observera att i bash måste en boolean true och false vara gemener som i: bool_true = true bool_false = false Alla andra fall kommer utvärdera som strängar och inte booleska.

Så med ditt exempel och James Ko: s svar skulle det vara:

phone_missing=false echo "missing $phone_missing" if ! $phone_missing then echo "Lost phone at $readabletime" $phone_missing=true fi 

eller som jag föredrar för läsbarhet (syntaktiskt samma och James Ko ”s)

phone_missing=false echo "missing $phone_missing" if ( ! $phone_missing ); then echo "Lost phone at $readabletime" $phone_missing=true fi 

Andra svar som t.ex. av Alexios kontrollerar bokstavligen stränginnehållet. Så att något av följande skulle leda till falskt:

phone_missing=false if [ "$phone_missing" != false ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi if [ "$phone_missing" == true ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi if [ "$phone_missing" == Bobs_your_uncle ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi 

Svar

Den korrekta syntaxen är if ! $bool; then [statements]; fi.

Exempel:

bool=false if ! $bool; then echo "This is correct!" fi if [ ! $bool ]; then echo "This is wrong!" fi 

Utgång: This is correct!

Kommentarer

  • Det finns en sanningskärna i ditt svar, men utan förklaring orsakar det mer förvirring än det botar. Det är också lite mer än en upprepning av ett av de tidigare svaren. Om du inte vill att ditt svar ska tas bort, förklara varför det är rätt.

Lämna ett svar

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