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 true
op 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, var
in 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 test
of [[
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
- Miku’s antwoord is sindsdien aangepast en bevat geen (bekende) gebreken meer.
- Geen uitputtende lijst.
- 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 woman
zou nog steeds als een geldig commando worden beschouwd, zelfs als zo’n man-pagina niet bestaat. - Voor ongeldige (niet-bestaande) opdrachten, zal Bash gewoon klagen dat de opdracht niet is gevonden.
- 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 true
commando . In dit geval is true
niets 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 yeah
aan te roepen, en er is (in het voorbeeld van miku) ook geen speciale behandeling gaande wanneer Bash het token true
ontleedt. 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:
- Breid de variabele
$the_world_is_flat
uit tot de tekenreeks"true"
. - Probeer de tekenreeks
"true"
als een opdracht te ontleden. - Zoek en voer de opdracht
true
uit (een ingebouwd of/bin/true
, afhankelijk van de Bash-versie). - 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. - Aangezien de exit-code 0 was (succes), voert u de
then
-instructie uitthen
-clausule
Beugels:
- Breid de variabele
$the_world_is_flat
uit tot de tekenreeks"true"
. - Ontleed de nu volledig uitgebreide voorwaardelijke expressie, die de vorm
string1 = string2
heeft. De operator=
is de tekenreeksvergelijking-operator van bash. Dus… - Voer een stringvergelijking uit op
"true"
en"true"
. - Ja, de twee strings waren hetzelfde, dus de waarde van de voorwaardelijke is waar.
- Voer de
then
-clausule van dethen
-instructie uit.
De code zonder haakjes werkt, omdat de opdracht true
een afsluitcode van 0 retourneert, wat aangeeft dat het gelukt is. De code tussen haakjes werkt, omdat de waarde van $the_world_is_flat
identiek is aan de letterlijke tekenreeks true
aan 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 var
is "=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 true
en false
commando’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 true
of false
ziet 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 true
is. De voorwaarde is waar wanneer de opdracht exitcode 0 retourneert. true
en false
zijn 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 COMMAND
hier is [[
met de parameters 1 == 1 ]]
De if..then..fi
constructie 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 true
en false
gebruikt 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 true
en 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 sh
hadden, werden Booleans afgehandeld door te vertrouwen op een conventie van het programma test
waarbij test
een 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 test
ingebouwd 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 test
nabootst, 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 r
optie in declare
en readonly
wordt 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 true
of false
op een regel op zichzelf stelt de retourwaarde voor het blok waarin u zich bevindt in op die waarde, dwz false
is 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 true
in 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 true
zich gedraagt als 1
en false
gedraagt 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
((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.
-
[
en]
haakjes zoals in[ "$var" = true ]
zijn niet nodig en u kunt ze weglaten en gebruik de opdrachttest
rechtstreeks: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.
-
Stel je voor wat die woorden
true
enfalse
betekenen 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.
-
Wat betekent dit? Nou, verschillende dingen.
-
Je moet eraan wennen dat Booleaanse trefwoorden eigenlijk als getallen worden behandeld, dat wil zeggen
true
=0
enfalse
=1
, onthoud dat alle waarden die niet nul zijn, worden behandeld alsfalse
. -
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 nummer0
dat staat voortrue
of1
staat voor respectievelijkfalse
. -
Ten slotte, wat moet je doen met al die informatie
-
Ten eerste is het een goede gewoonte om
0
toe te wijzen in plaats vantrue
;1
in plaats vanfalse
. -
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 -eq
een 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 -eq
voor 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 $snapshotEvents
evalueert 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.
-
Getest op: GNU Bash, versie 4.1.11(2)-release
-
Bash-gids voor beginners, Machtelt Garrels, v1.11, 2008
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 false
is:
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.