Hoe kan ik Booleaanse variabelen declareren en gebruiken in een shellscript?

Ik heb geprobeerd een Booleaanse variabele in een shellscript te declareren met de volgende syntaxis:

variable=$false
variable=$true

Is dit correct? En als ik die variabele zou willen bijwerken, zou ik dan dezelfde syntaxis gebruiken? Ten slotte, is de volgende syntaxis voor het gebruik van Booleaanse variabelen als uitdrukkingen correct?

if [ $variable ]
if [ !$variable ]

Antwoord 1, autoriteit 100%

Herzien antwoord (12 februari 2014)

the_world_is_flat=true
# ...do something interesting...
if [ "$the_world_is_flat" = true ] ; then
    echo 'Be careful not to fall off!'
fi

Oorspronkelijk antwoord

Voorbehoud: https://stackoverflow.com/a/21210966/89391

the_world_is_flat=true
# ...do something interesting...
if $the_world_is_flat ; then
    echo 'Be careful not to fall off!'
fi

Van: Boolean gebruiken variabelen in Bash

De reden waarom het oorspronkelijke antwoord hier is opgenomen, is omdat de opmerkingen vóór de revisie op 12 februari 2014 alleen betrekking hebben op het oorspronkelijke antwoord, en veel van de opmerkingen zijn onjuist wanneer ze worden gekoppeld aan het herziene antwoord. De opmerking van Dennis Williamson over bash builtin trueop 2 juni 2010 is bijvoorbeeld alleen van toepassing op het oorspronkelijke antwoord, niet op het herziene antwoord.


Antwoord 2, autoriteit 65%

TL;DR

my_bool=true
if [ "$my_bool" = true ]

Problemen met Miku’s (originele) antwoord

Ik beveel niethet geaccepteerde antwoord1aan. De syntaxis is mooi, maar er zijn enkele gebreken.

Stel dat we de volgende voorwaarde hebben.

if $var; then
  echo 'Muahahaha!'
fi

In de volgende gevallen2wordt deze voorwaarde geëvalueerd tot trueen wordt de geneste opdracht uitgevoerd.

# Variable var not defined beforehand. Case 1
var=''  # Equivalent to var="".      # Case 2
var=                                 # Case 3
unset var                            # Case 4
var='<some valid command>'           # Case 5

Normaal gesproken wilt u dat uw voorwaarde alleen wordt geëvalueerd als waar als uw “Boolean”-variabele, varin dit voorbeeld, expliciet is ingesteld op waar. Alle andere gevallen zijn gevaarlijk misleidend!

Het laatste geval (#5) is vooral ondeugend omdat het de opdracht in de variabele zal uitvoeren (daarom wordt de voorwaarde geëvalueerd als waar voor geldige opdrachten3, 4).

Hier is een onschuldig voorbeeld:

var='echo this text will be displayed when the condition is evaluated'
if $var; then
  echo 'Muahahaha!'
fi
# Outputs:
# this text will be displayed when the condition is evaluated
# Muahahaha!

Het citeren van uw variabelen is veiliger, b.v. if "$var"; then. In de bovenstaande gevallen zou u een waarschuwing moeten krijgen dat de opdracht niet is gevonden. Maar we kunnen nog steeds beter doen (zie mijn aanbevelingen onderaan).

Zie ook Mike Holts uitleg van Miku’s oorspronkelijke antwoord.

Problemen met Hbar’s antwoord

Deze aanpak heeft ook onverwacht gedrag.

var=false
if [ $var ]; then
  echo "This won't print, var is false!"
fi
# Outputs:
# This won't print, var is false!

Je zou verwachten dat de bovenstaande voorwaarde op false evalueert, en dus nooit de geneste instructie uitvoert. Verrassing!

De waarde citeren ("false"), de variabele citeren ("$var"), of testof [[in plaats van [, maak geen verschil.

Wat ik doeaanbeveel:

Hier zijn manieren waarop ik u aanraad uw “Booleans” te controleren. Ze werken zoals verwacht.

my_bool=true
if [ "$my_bool" = true ]; then
if [ "$my_bool" = "true" ]; then
if [[ "$my_bool" = true ]]; then
if [[ "$my_bool" = "true" ]]; then
if [[ "$my_bool" == true ]]; then
if [[ "$my_bool" == "true" ]]; then
if test "$my_bool" = true; then
if test "$my_bool" = "true"; then

Ze zijn allemaal vrijwel gelijk. Je moet een paar toetsaanslagen meer typen dan de benaderingen in de andere antwoorden5, maar je code zal defensiever zijn.


Voetnoten

  1. Miku’s antwoord is sindsdien aangepast en bevat geen (bekende) gebreken meer.
  2. Geen uitputtende lijst.
  3. Een geldig commando in deze context betekent een commando dat bestaat. Het maakt niet uit of de opdracht correct of onjuist wordt gebruikt. bijv. man womanzou nog steeds als een geldig commando worden beschouwd, zelfs als zo’n man-pagina niet bestaat.
  4. Voor ongeldige (niet-bestaande) opdrachten, zal Bash gewoon klagen dat de opdracht niet is gevonden.
  5. Als je om lengte geeft, is de eerste aanbeveling de kortste.

Antwoord 3, autoriteit 13%

Er lijkt hier een misverstand te bestaan ​​over de ingebouwde Bash true, en meer specifiek over hoe Bash uitdrukkingen tussen haakjes uitbreidt en interpreteert.

De code in miku’s antwoord heeft absoluut niets te maken met de Bash ingebouwde true, noch /bin/true, noch enige andere smaak van het truecommando . In dit geval is trueniets meer dan een eenvoudige tekenreeks en wordt er nooit een aanroep gedaan naar het true-commando/ingebouwd, noch door de variabele toewijzing, noch door de evaluatie van de voorwaardelijke uitdrukking.

De volgende code is functioneel identiek aan de code in het antwoord van de miku:

the_world_is_flat=yeah
if [ "$the_world_is_flat" = yeah ]; then
    echo 'Be careful not to fall off!'
fi

Het enigeverschil hier is dat de vier tekens die worden vergeleken ‘y’, ‘e’, ​​’a’ en ‘h’ zijn in plaats van ‘t’, ‘r’, ‘u ‘, en ‘e’. Dat is het. Er is geen poging gedaan om een ​​commando of ingebouwde functie met de naam yeahaan te roepen, en er is (in het voorbeeld van miku) ook geen speciale behandeling gaande wanneer Bash het token trueontleedt. Het is maar een string, en nog een volledig willekeurige.

Update (2014-02-19):Na het volgen van de link in het antwoord van miku, zie ik nu waar een deel van de verwarring vandaan komt. Miku’s antwoord gebruikt enkele haakjes, maar het codefragment waarnaar hij linkt, gebruikt geen haakjes. Het is gewoon:

the_world_is_flat=true
if $the_world_is_flat; then
  echo 'Be careful not to fall off!'
fi

Beide codefragmenten zullen zich gedragenop dezelfde manier, maar de haakjes veranderen volledig wat er onder de motorkap gebeurt.

Dit is wat Bash in elk geval doet:

Geen haakjes:

  1. Breid de variabele $the_world_is_flatuit tot de tekenreeks "true".
  2. Probeer de tekenreeks "true"als een opdracht te ontleden.
  3. Zoek en voer de opdracht trueuit (een ingebouwd of /bin/true, afhankelijk van de Bash-versie).
  4. Vergelijk de exit-code van het true-commando (dat altijd 0 is) met 0. Bedenk dat in de meeste shells een exit-code van 0 succes aangeeft en al het andere een mislukking.
  5. Aangezien de exit-code 0 was (succes), voert u de then-instructie uit then-clausule

Beugels:

  1. Breid de variabele $the_world_is_flatuit tot de tekenreeks "true".
  2. Ontleed de nu volledig uitgebreide voorwaardelijke expressie, die de vorm string1 = string2heeft. De operator =is de tekenreeksvergelijking-operator van bash. Dus…
  3. Voer een stringvergelijking uit op "true"en "true".
  4. Ja, de twee strings waren hetzelfde, dus de waarde van de voorwaardelijke is waar.
  5. Voer de then-clausule van de then-instructie uit.

De code zonder haakjes werkt, omdat de opdracht trueeen afsluitcode van 0 retourneert, wat aangeeft dat het gelukt is. De code tussen haakjes werkt, omdat de waarde van $the_world_is_flatidentiek is aan de letterlijke tekenreeks trueaan de rechterkant van de =.

Om het punt naar huis te brengen, overweeg de volgende twee codefragmenten:

Deze code (indien uitgevoerd met root-rechten) zal uw computer opnieuw opstarten:

var=reboot
if $var; then
  echo 'Muahahaha! You are going down!'
fi

Deze code drukt alleen ‘Leuke poging’ af. Het reboot-commando wordt niet aangeroepen.

var=reboot
if [ $var ]; then
  echo 'Nice try.'
fi

Update (2014-04-14)Om de vraag in de opmerkingen over het verschil tussen =en ==te beantwoorden: AFAIK, er is geen verschil. De operator ==is een Bash-specifiek synoniem voor =, en voor zover ik heb gezien, werken ze in alle contexten precies hetzelfde.

Houd er echter rekening mee dat ik het specifiek heb over de =en ==tekenreeksvergelijkingsoperatoren die worden gebruikt in [ ]of [[ ]]testen. Ik suggereer niet dat =en ==overaluitwisselbaar zijn in bash.

Je kunt bijvoorbeeld natuurlijk geen variabele toewijzing doen met ==, zoals var=="foo"(technisch gezien kun je weldoe dit, maar de waarde van varis "=foo", omdat Bash hier geen operator ==ziet, het ziet een =(toewijzing) operator, gevolgd door de letterlijke waarde ="foo", die gewoon "=foo"wordt).

Ook, hoewel =en ==onderling uitwisselbaar zijn, moet u er rekening mee houden dat hoe deze tests afhankelijkafhangt van of u’ gebruik het binnen [ ]of [[ ]], en ook of de operanden al dan niet worden geciteerd. U kunt daar meer over lezen in Advanced Bash Scripting Guide: 7.3 Other Vergelijkingsoperators(scroll naar beneden naar de bespreking van =en ==).


Antwoord 4, autoriteit 5%

Gebruik rekenkundige uitdrukkingen.

#!/bin/bash
false=0
true=1
((false)) && echo false
((true)) && echo true
((!false)) && echo not false
((!true)) && echo not true

Uitvoer:

waar
niet onwaar


Antwoord 5, autoriteit 4%

Lang verhaal kort:

Er zijn geen Booleans in Bash

De trueen falsecommando’s

Bash heeft wel Booleaanse uitdrukkingen in termen van vergelijking en voorwaarden. Dat gezegd hebbende, wat je in Bash kunt declareren en vergelijken, zijn strings en getallen. Dat is het.

Waar je ook trueof falseziet in Bash, het is een tekenreeks of een commando/ingebouwd dat alleen wordt gebruikt voor de afsluitcode.

Deze syntaxis…

if true; then ...

is in wezen…

if COMMAND; then ...

waarbij het commando trueis. De voorwaarde is waar wanneer de opdracht exitcode 0 retourneert. trueen falsezijn ingebouwde Bash- en soms ook zelfstandige programma’s die niets anders doen dan de bijbehorende exitcode retourneren.


Voorwaarden in if..then..fi

Als je vierkante haken gebruikt of de opdracht test, vertrouw je op de afsluitcode van die constructie. Houd er rekening mee dat [ ]en [[ ]]ook gewoon commando’s/ingebouwde onderdelen zijn zoals alle andere. Dus …

if [[ 1 == 1 ]]; then echo yes; fi

komt overeen met

if COMMAND; then echo yes; fi

en het COMMANDhier is [[met de parameters 1 == 1 ]]

De if..then..ficonstructie is gewoon syntactische suiker. U kunt de opdrachten altijd gewoon uitvoeren, gescheiden door een dubbele ampersand voor hetzelfde effect:

[[ 1 == 1 ]] && echo yes

Als je trueen falsegebruikt in deze testconstructies, geef je eigenlijk alleen de string "true"of "false"aan het testcommando. Hier is een voorbeeld:

Geloof het of niet, maar deze omstandigheden leveren allemaal hetzelfde resultaatop:

if [[ false ]]; then ...
if [[ "false" ]]; then ...
if [[ true ]]; then ...
if [[ "true" ]]; then ...

TL;DR; altijd vergelijken met tekenreeksen of getallen

Om dit voor toekomstige lezers duidelijk te maken, raad ik aan om altijd aanhalingstekens te gebruiken rond trueen false:

DOEN

if [[ "${var}" == "true" ]]; then ...
if [[ "${var}" == "false" ]]; then ...
if [[ "${var}" == "yes" ]]; then ...
if [[ "${var}" == "USE_FEATURE_X" ]]; then ...
if [[ -n "${var:- }" ]]; then echo "var is not empty" ...

NIET

# Always use double square brackets in bash!
if [ ... ]; then ...
# This is not as clear or searchable as -n
if [[ "${var}" ]]; then ...
# Creates impression of Booleans
if [[ "${var}" != true ]]; then ...
# `-eq` is for numbers and doesn't read as easy as `==`
if [[ "${var}" -eq "true" ]]; then ...

Misschien

# Creates impression of Booleans.
# It can be used for strict checking of dangerous operations.
# This condition is false for anything but the literal string "true".
if [[ "${var}" != "true" ]]; then ... 

Antwoord 6

Lang geleden, toen we alleen nog shhadden, werden Booleans afgehandeld door te vertrouwen op een conventie van het programma testwaarbij testeen valse exit-status indien uitgevoerd zonder argumenten.

Hierdoor kan men een variabele die is uitgeschakeld als onwaar beschouwen en een variabele die op elke waarde is ingesteld als waar. Tegenwoordig is testingebouwd in Bash en is algemeen bekend onder de alias van één teken [(of een uitvoerbaar bestand om te gebruiken in shells die het missen, zoals dolmen opmerkt):

FLAG="up or <set>"
if [ "$FLAG" ] ; then
    echo 'Is true'
else
    echo 'Is false'
fi
# Unset FLAG
#    also works
FLAG=
if [ "$FLAG" ] ; then
    echo 'Continues true'
else
    echo 'Turned false'
fi

Vanwege citatieconventies gebruiken scriptschrijvers liever het samengestelde commando [[dat testnabootst, maar een mooiere syntaxis heeft: variabelen met spaties hoeven niet geciteerd; men kan &&en ||gebruiken als logische operatoren met rare voorrang, en er zijn geen POSIX-beperkingen op het aantal termen.

Bijvoorbeeld om te bepalen of VLAG is ingesteld en COUNT een getal groter dan 1 is:

FLAG="u p"
COUNT=3
if [[ $FLAG  && $COUNT -gt '1' ]] ; then
    echo 'Flag up, count bigger than 1'
else
    echo 'Nope'
fi

Dit dingen kunnen verwarrend zijnwanneer spaties, strings met lengte nul en null-variabelen allemaal nodig zijn en ook wanneer je script met verschillende shells moet werken.


Antwoord 7

Hoe kan ik Booleaanse variabelen declareren en gebruiken in een shellscript?

In tegenstelling tot veel andere programmeertalen, scheidt Bash zijn variabelen niet op ‘type’. [1]

Dus het antwoord is vrij duidelijk. Er is geen Booleaanse variabelein Bash.

Echter:

Met een verklaring declareren kunnen we de waardetoewijzing beperken tot
variabelen.[2]

#!/bin/bash
declare -ir BOOL=(0 1) # Remember BOOL can't be unset till this shell terminates
readonly false=${BOOL[0]}
readonly true=${BOOL[1]}
# Same as declare -ir false=0 true=1
((true)) && echo "True"
((false)) && echo "False"
((!true)) && echo "Not True"
((!false)) && echo "Not false"

De roptie in declareen readonlywordt gebruikt om expliciet aan te geven dat de variabelen readonlyzijn. Ik hoop dat het doel duidelijk is.


Antwoord 8

Waarom niet gewoon een betere waarde gebruiken dan waar en onwaar, in plaats van een Boolean te vervalsen en een val voor toekomstige lezers te laten?

Bijvoorbeeld:

build_state=success
if something-horrible; then
  build_state=failed
fi
if [[ "$build_state" == success ]]; then
  echo go home; you are done
else
  echo your head is on fire; run around in circles
fi

Antwoord 9

Mijn bevindingen en suggestie wijken een beetje af van de andere posts. Ik ontdekte dat ik “booleans” in principe kon gebruiken zoals in elke “gewone” taal, zonder de suggestie van “hoepelspringen”…

Er is geen behoefte aan []of expliciete stringvergelijkingen… Ik heb meerdere Linux-distributies geprobeerd. Ik heb Bash, Dash en BusyBoxgetest. De resultaten waren altijd hetzelfde. Ik weet niet zeker waar de originele posts met de meeste stemmen over gaan. Misschien zijn de tijden veranderd en is dat alles?

Als u een variabele instelt op true, wordt deze vervolgens geëvalueerd als een “bevestigend” binnen een voorwaardelijke. Stel het in op false, en het evalueert naar een “negatief”. Heel eenvoudig! Het enige voorbehoud is dat een undefinedvariabele ook als trueevalueert! Het zou leuk zijn als het het tegenovergestelde deed (zoals in de meeste talen), maar dat is de truc – je hoeft alleen je booleans expliciet te initialiseren naar waar of onwaar.

Waarom werkt het op deze manier? Dat antwoord is tweeledig. A) waar/onwaar in een shell betekent echt “geen fout” versus “fout” (d.w.z. 0 versus iets anders). B) waar/onwaar zijn geen waarden – maar eerder statementsin shell-scripting! Wat betreft het tweede punt, het uitvoeren van trueof falseop een regel op zichzelf stelt de retourwaarde voor het blok waarin u zich bevindt in op die waarde, dwz falseis een verklaring van “error gevonden”, waar true dat “wist”. Als u het gebruikt met een toewijzing aan een variabele, “geeft” u dat terug in de variabele. Een undefinedvariabele evalueert als truein een voorwaardelijke omdat die gelijk staat aan 0 of “geen fout aangetroffen”.

Zie de voorbeeld Bash-lijnen en resultaten hieronder. Test het zelf als je het wilt bevestigen…

#!/bin/sh
# Not yet defined...
echo "when set to ${myBool}"
if ${myBool}; then echo "it evaluates to true"; else echo "it evaluates to false"; fi;
myBool=true
echo "when set to ${myBool}"
if ${myBool}; then echo "it evaluates to true"; else echo "it evaluates to false"; fi;
myBool=false
echo "when set to ${myBool}"
if ${myBool}; then echo "it evaluates to true"; else echo "it evaluates to false"; fi;

Opbrengsten

when set to
it evaluates to true
when set to true
it evaluates to true
when set to false
it evaluates to false

Antwoord 10

In veel programmeertalen is het Booleaanse type een subtype van een geheel getal, of wordt het geïmplementeerd als een subtype van integer, waarbij truezich gedraagt ​​als 1en falsegedraagt ​​zich als 0:

Wiskundiglijkt Booleaanse algebra op gehele rekenkunde modulo 2. Daarom, als een taal niet Om een ​​native Boolean-type te bieden, is de meest natuurlijke en efficiënte oplossing het gebruik van gehele getallen. Dit werkt met bijna elke taal. In Bash kun je bijvoorbeeld het volgende doen:

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

man bash:

((uitdrukking))

De uitdrukking wordt geëvalueerd volgens de regels die hieronder worden beschreven onder ARITHMETIC EVALUATION. Als de waarde van de expressie niet nul is, is de retourstatus 0; anders is de retourstatus 1. Dit is exact gelijk aan let “uitdrukking”.


Antwoord 11

POSIX(draagbare besturingssysteeminterface)

Ik mis hier het belangrijkste punt, namelijk draagbaarheid. Daarom heeft mijn kop POSIXop zich.

In wezen zijn alle gestemde antwoorden correct, met uitzondering van Bash-specifiek te veel.

Eigenlijk wil ik alleen meer informatie over draagbaarheid toevoegen.


  1. [en ]haakjes zoals in [ "$var" = true ]zijn niet nodig en u kunt ze weglaten en gebruik de opdracht testrechtstreeks:

    test "$var" = true && yourCodeIfTrue || yourCodeIfFalse
    

    Belangrijke opmerking: Ik raad dit niet langer aanomdat het langzaam wordt afgeschaft en het moeilijker wordt om meerdere verklaringen te combineren.

  2. Stel je voor wat die woorden trueen falsebetekenen voor de shell, test het zelf:

    echo $(( true ))
    
    0
    
    echo $(( false ))
    
    1
    

    Maar aanhalingstekens gebruiken:

    echo $(( "true" ))
    
    bash: "true": syntax error: operand expected (error token is ""true"")
    sh (dash): sh: 1: arithmetic expression: expecting primary: ""true""
    

    Hetzelfde geldt voor:

    echo $(( "false" ))
    

    De shell kan het niet anders interpreteren dan een string. Ik hoop dat je een idee krijgt van hoe goed het is om het juiste zoekwoord zonder aanhalingstekenste gebruiken.

    Maar niemand zei het in eerdere antwoorden.

  3. Wat betekent dit? Nou, verschillende dingen.

    • Je moet eraan wennen dat Booleaanse trefwoorden eigenlijk als getallen worden behandeld, dat wil zeggen true= 0en false= 1, onthoud dat alle waarden die niet nul zijn, worden behandeld als false.

    • Omdat ze als getallen worden behandeld, moet je ze ook zo behandelen, d.w.z. als je een variabele definieert, zeg dan:

      var_bool=true
      echo "$var_bool"
      
      true
      

      je kunt er een tegengestelde waarde van maken met:

      var_bool=$(( 1 - $var_bool ))  # same as $(( ! $var_bool ))
      echo "$var_bool"
      
      1
      

    Zoals je zelf kunt zien, drukt de shell de true-tekenreeks af voor de eerste keer dat je hem gebruikt, maar sindsdien werkt het allemaal via nummer 0dat staat voor trueof 1staat voor respectievelijk false.


Ten slotte, wat moet je doen met al die informatie

  • Ten eerste is het een goede gewoonte om 0toe te wijzen in plaats van true; 1in plaats van false.

  • Een tweede goede gewoonte zou zijn om te testen of de variabele wel/niet gelijk is aan nul:

    if [ "$var_bool" -eq 0 ]; then
         yourCodeIfTrue
    else
         yourCodeIfFalse
    fi
    

Antwoord 12

Wat de syntaxis betreft, dit is een eenvoudige methode die ik (bijvoorbeeld) gebruik om de Booleaanse logica consequent en verstandig te beheren:

# Tests
var=
var=''
var=""
var=0
var=1
var="abc"
var=abc
if [[ -n "${var}" ]] ; then
    echo 'true'
fi
if [[ -z "${var}" ]] ; then
    echo 'false'
fi
# Results
# var=        # false
# var=''      # false
# var=""      # false
# var=0       # true
# var=1       # true
# var="abc"   # true
# var=abc     # true

Als de variabele nooit wordt gedeclareerd, is het antwoord: # false

Dus een eenvoudige manier om een ​​variabele op true in te stellen (met behulp van deze syntaxismethodologie) zou zijn: var=1; omgekeerd, var=''.

Referentie:

-n= Waar als de lengte van de var-tekenreeks niet nul is.

-z= Waar als de lengte van de var-tekenreeks nul is.


Antwoord 13

Bill Parker wordt gestemd down, omdat zijn definities zijn omgekeerd van de normale codeconventie. Normaal gesproken wordt waar gedefinieerd als 0 en onwaar wordt gedefinieerd als niet-nul. 1 werkt voor false, evenals 9999 en -1. Hetzelfde geldt voor functieretourwaarden – 0 is succes en alles wat niet nul is, is een mislukking. Sorry, ik heb nog niet de geloofwaardigheid van de straat om te stemmen of rechtstreeks op hem te reageren.

Bash raadt aan om nu dubbele haakjes te gebruiken in plaats van enkele haakjes, en de link die Mike Holt gaf legt de verschillen uit in hoe ze werken. 7.3. Andere vergelijkingsoperators

Om te beginnen is -eqeen numerieke operator, dus met de code

#**** NOTE *** This gives error message *****
The_world_is_flat=0;
if [ "${The_world_is_flat}" -eq true ]; then

geeft een foutmelding en verwacht een integer-expressie. Dit is van toepassing op beide parameters, aangezien geen van beide een geheel getal is. Maar als we er dubbele haakjes omheen zetten, zal het geen foutmelding geven, maar het zal een verkeerde waarde opleveren (nou ja, in 50% van de mogelijke permutaties). Het zal worden geëvalueerd tot [[0 -eq true]] = succes, maar ook tot [[0 -eq false]] = succes, wat niet klopt (hmmm… hoe zit het met dat ingebouwde een numerieke waarde is?).

#**** NOTE *** This gives wrong output *****
The_world_is_flat=true;
if [[ "${The_world_is_flat}" -eq true ]]; then

Er zijn andere permutaties van de voorwaardelijke die ook een verkeerde uitvoer geven. Kortom, alles (behalve de hierboven vermelde foutconditie) dat een variabele instelt op een numerieke waarde en deze vergelijkt met een ingebouwde waar/onwaar, of een variabele instelt op een ingebouwde waar/onwaar en deze vergelijkt met een numerieke waarde. Ook alles dat een variabele instelt op een ingebouwde true/false en een vergelijking maakt met behulp van -eq. Vermijd dus -eqvoor Booleaanse vergelijkingen en vermijd het gebruik van numerieke waarden voor Booleaanse vergelijkingen. Hier is een samenvatting van de permutaties die ongeldige resultaten zullen geven:

# With variable set as an integer and evaluating to true/false
# *** This will issue error warning and not run: *****
The_world_is_flat=0;
if [ "${The_world_is_flat}" -eq true ]; then
# With variable set as an integer and evaluating to true/false
# *** These statements will not evaluate properly: *****
The_world_is_flat=0;
if [ "${The_world_is_flat}" -eq true ]; then
#
if [[ "${The_world_is_flat}" -eq true ]]; then
#
if [ "${The_world_is_flat}" = true ]; then
#
if [[ "${The_world_is_flat}" = true ]]; then
#
if [ "${The_world_is_flat}" == true ]; then
#
if [[ "${The_world_is_flat}" == true ]]; then
# With variable set as an true/false builtin and evaluating to true/false
# *** These statements will not evaluate properly: *****
The_world_is_flat=true;
if [[ "${The_world_is_flat}" -eq true ]]; then
#
if [ "${The_world_is_flat}" = 0 ]; then
#
if [[ "${The_world_is_flat}" = 0 ]]; then
#
if [ "${The_world_is_flat}" == 0 ]; then
#
if [[ "${The_world_is_flat}" == 0 ]]; then

Dus nu naar wat werkt. Gebruik true/false ingebouwde ins voor zowel je vergelijking als je evaluaties (zoals Mike Hunt opmerkte, zet ze niet tussen aanhalingstekens). Gebruik dan een of enkel of dubbel gelijkteken (= of ==) en enkele of dubbele haakjes ([ ] of [[ ]]). Persoonlijk hou ik van het dubbele gelijkteken, omdat het me doet denken aan logische vergelijkingen in andere programmeertalen, en dubbele aanhalingstekens, gewoon omdat ik van typen houd. Dus deze werken:

# With variable set as an integer and evaluating to true/false
# *** These statements will work properly: *****
#
The_world_is_flat=true/false;
if [ "${The_world_is_flat}" = true ]; then
#
if [[ "${The_world_is_flat}" = true ]]; then
#
if [ "${The_world_is_flat}" = true ]; then
#
if [[ "${The_world_is_flat}" == true ]]; then

Daar heb je het.


Antwoord 14

Mijn recept voor (mijn eigen) idiotie:

# setting ----------------
commonMode=false
if [[ $something == 'COMMON' ]]; then
    commonMode=true
fi
# using ----------------
if $commonMode; then
    echo 'YES, Common Mode'
else
    echo 'NO, no Common Mode'
fi
$commonMode && echo 'commonMode is ON  ++++++'
$commonMode || echo 'commonMode is OFF xxxxxx'

Antwoord 15

Hier is een eenvoudig voorbeeld dat voor mij werkt:

temp1=true
temp2=false
if [ "$temp1" = true ] || [ "$temp2" = true ]
then
    echo "Do something." 
else
    echo "Do something else."
fi

Antwoord 16

Hier is een implementatie van een short-handed if true.

# Function to test if a variable is set to "true"
_if () {
    [ "${1}" == "true" ] && return 0
    [ "${1}" == "True" ] && return 0
    [ "${1}" == "Yes" ] && return 0
    return 1
}

Voorbeeld 1

my_boolean=true
_if ${my_boolean} && {
    echo "True Is True"
} || {
    echo "False Is False"
}

Voorbeeld 2

my_boolean=false
! _if ${my_boolean} && echo "Not True is True"

Antwoord 17

Ik vond de bestaande antwoorden verwarrend.

Persoonlijk wil ik gewoon iets hebben dat eruitziet en werkt als C.

Dit fragment werkt vele malen per dag in productie:

snapshotEvents=true
if ($snapshotEvents)
then
    # Do stuff if true
fi

en om iedereen tevreden te houden, heb ik getest:

snapshotEvents=false
if !($snapshotEvents)
then
    # Do stuff if false
fi

Wat ook prima werkte.

De $snapshotEventsevalueert de inhoud van de waarde van de variabele. Je hebt dus de $nodig.

Je hebt de haakjes niet echt nodig, ik vind ze gewoon handig.


Antwoord 18

Hier is een verbetering ten opzichte van miku’s oorspronkelijke antwoorddat betrekking heeft op De zorgen van Dennis Williamsonover het geval waarin de variabele niet is ingesteld:

the_world_is_flat=true
if ${the_world_is_flat:-false} ; then
    echo "Be careful not to fall off!"
fi

En om te testen of de variabele falseis:

if ! ${the_world_is_flat:-false} ; then
    echo "Be careful not to fall off!"
fi

Over andere gevallen met een vervelende inhoud in de variabele, dit is een probleem met externe invoer die naar een programma wordt gevoerd.

Elke externe invoer moet worden gevalideerd voordat u deze kunt vertrouwen. Maar die validatie hoeft maar één keer te gebeuren, wanneer die invoer is ontvangen.

Het hoeft geen invloed te hebben op de prestaties van het programma door het te doen bij elk gebruik van de variabele, zoals Dennis Williamsonsuggereert.


Antwoord 19

Je kunt shFlagsgebruiken.

Het geeft je de mogelijkheid om te definiëren: DEFINE_bool

Voorbeeld:

DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing");

Vanaf de opdrachtregel kunt u het volgende definiëren:

sh script.sh --bigmenu
sh script.sh --nobigmenu # False

Antwoord 20

Een andere manier om booleans te gebruiken is om de leegtevan waarden te testen. Dit heeft als voordeel dat je kortere tests kunt maken:

first=1  # A true value
second=   # A false value
[ -n "$first" ]  && echo 'First var is true'
[ -z "$first" ]  && echo 'First var is false'
[ -n "$second" ] && echo 'Second var is true'
[ -z "$second" ] && echo 'Second var is false'

Uitvoer:

First var is true
Second var is false

Hier is een alternatieve testsyntaxis met bash: [[ -n $one ]]


Antwoord 21

Dit is een snelheidstest over verschillende manieren om “Booleaanse” waarden in Bash te testen:

#!/bin/bash
rounds=100000
b=true # For true; b=false for false
type -a true
time for i in $(seq $rounds); do command $b; done
time for i in $(seq $rounds); do $b; done
time for i in $(seq $rounds); do [ "$b" == true ]; done
time for i in $(seq $rounds); do test "$b" == true; done
time for i in $(seq $rounds); do [[ $b == true ]]; done
b=x; # Or any non-null string for true; b='' for false
time for i in $(seq $rounds); do [ "$b" ]; done
time for i in $(seq $rounds); do [[ $b ]]; done
b=1 # Or any non-zero integer for true; b=0 for false
time for i in $(seq $rounds); do ((b)); done

Het zou zoiets als

. afdrukken

true is a shell builtin
true is /bin/true
real    0m0,815s
user    0m0,767s
sys     0m0,029s
real    0m0,562s
user    0m0,509s
sys     0m0,022s
real    0m0,829s
user    0m0,782s
sys     0m0,008s
real    0m0,782s
user    0m0,730s
sys     0m0,015s
real    0m0,402s
user    0m0,391s
sys     0m0,006s
real    0m0,668s
user    0m0,633s
sys     0m0,008s
real    0m0,344s
user    0m0,311s
sys     0m0,016s
real    0m0,367s
user    0m0,347s
sys     0m0,017s

Antwoord 22

Alternatief – gebruik een functie

is_ok(){ :;}
is_ok(){ return 1;}
is_ok && echo "It's OK" || echo "Something's wrong"

Het definiëren van de functie is minder intuïtief, maar het controleren van de geretourneerde waarde is heel eenvoudig.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes