Wie kann ich boolesche Variablen in einem Shell-Skript deklarieren und verwenden?

979

Ich habe versucht, eine boolesche Variable in einem Shell-Skript mit der folgenden Syntax zu deklarieren:

variable=$false

variable=$true

Ist das richtig? Wenn ich diese Variable aktualisieren wollte, würde ich dieselbe Syntax verwenden? Ist die folgende Syntax für die Verwendung von Booleschen Variablen als Ausdrücke korrekt?

if [ $variable ]

if [ !$variable ]
Hassaanm
quelle
73
IN ACHT NEHMEN! trueund falseim Zusammenhang mit den meisten Schnipsel unten sind nur einfache Zeichenfolgen, nicht die bash built-ins!!! Bitte lesen Sie die Antwort von Mike Holt unten. (Dies ist ein Beispiel, wo eine hoch gewählte und akzeptierte Antwort
meiner Meinung nach
7
@mjv Die meiste Verwirrung über diese Frage (und Mikus Antwort) war auf die Tatsache zurückzuführen, dass Miku seine Antwort irgendwann überarbeitete, nachdem mehrere Kommentare veröffentlicht worden waren, in denen beschrieben wurde, wie Mikus Antwort das Aufrufen der eingebauten Bash beinhaltete true. Es stellte sich heraus, dass Mikus ursprüngliche Antwort die trueeingebaute Antwort wirklich anrief , die überarbeitete Antwort jedoch nicht. Dies führte dazu, dass diese Kommentare hinsichtlich der Funktionsweise von Mikus Code falsch zu sein schienen. Mikus Antwort wurde inzwischen bearbeitet, um sowohl den ursprünglichen als auch den überarbeiteten Code explizit anzuzeigen. Hoffentlich lässt dies die Verwirrung ein für alle Mal ruhen.
Mike Holt
2
[ true ] && echo yes, true is trueund (upppsss) [ false ] && echo yes, false is also true. / bin / true und / bin / false geben einen Rückkehrcode $? für Funktionen nicht zum Vergleich.
fcm
Wenn var gesetzt variable=somethingist, ist es wahr, wenn nicht gesetzt variable=, wäre das falsch [[ $variable ]] && echo true || echo falseund umgekehrt[[ ! $variable ]] && echo false || echo true
Ivan

Antworten:

1201

Überarbeitete Antwort (12. Februar 2014)

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

Ursprüngliche Antwort

Vorsichtsmaßnahmen: 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

Von: Verwenden von booleschen Variablen in Bash

Der Grund, warum die ursprüngliche Antwort hier enthalten ist, liegt darin, dass sich die Kommentare vor der Überarbeitung am 12. Februar 2014 nur auf die ursprüngliche Antwort beziehen und viele der Kommentare falsch sind, wenn sie mit der überarbeiteten Antwort verknüpft sind. Zum Beispiel gilt Dennis Williamsons Kommentar zu Bash, der trueam 2. Juni 2010 eingebaut wurde , nur für die ursprüngliche Antwort, nicht für die überarbeitete.

miku
quelle
37
Um zu erklären, was passiert: Die ifAnweisung führt den Inhalt der Variablen aus, die der integrierte Bash ist true. Jeder Befehl könnte als Wert der Variablen festgelegt und ihr Exit-Wert ausgewertet werden.
Bis auf weiteres angehalten.
7
@pms Die Operatoren "-o" und "-a" stehen nur für den Befehl "test" (auch bekannt als "[]"). Stattdessen ist dies "if + Befehl" ohne den "Test". (Wie "if grep foo file; then ...".) Verwenden Sie also die Operatoren normal &&und ||: # t1=true; t2=true; f1=false;# if $t1 || $f1; then echo is_true ; else echo is_false; fi; (gibt "true" zurück, da t1 = true) # if $t1 && $f1 || $t2; then echo is_true ; else echo is_false; fi (gibt "true" zurück, da t2 = true) . Auch dies funktioniert NUR, weil "true" / "false" Bash-Builtins sind (Rückgabe von true / false). Sie können "if $ var ..." nur verwenden, wenn var ein cmd ist (dh wahr oder falsch)
michael
14
-1, siehe meine Antwort für eine Erklärung.
Dennis
3
Viele falsche Informationen hier. / bin / true wird nicht effektiv verwendet. Siehe Dennis 'Antwort.
Ajk
1
Dieser Code ist nicht derselbe und funktioniert nicht wie der verlinkte Artikel. Der verknüpfte Code ruft ein Programm mit dem in einer Variablen gespeicherten Namen auf, aber der Code in dieser Antwort ist nur ein Zeichenfolgenvergleich.
Quolonel Fragen
794

TL; DR

bool=true

if [ "$bool" = true ]

Probleme mit Mikus ( Original- ) Antwort

Ich nicht empfehlen , die akzeptierte Antwort 1 . Die Syntax ist hübsch, weist jedoch einige Mängel auf.

Angenommen, wir haben die folgende Bedingung.

if $var; then
  echo 'Muahahaha!'
fi

In den folgenden Fällen 2 wird diese Bedingung als wahr ausgewertet und der verschachtelte Befehl ausgeführt.

# 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

Normalerweise möchten Sie, dass Ihre Bedingung nur dann als wahr ausgewertet wird, wenn Ihre "Boolesche" Variable varin diesem Beispiel explizit auf "wahr" gesetzt ist. Alle anderen Fälle sind gefährlich irreführend!

Der letzte Fall (# 5) ist besonders ungezogen, da er den in der Variablen enthaltenen Befehl ausführt (weshalb die Bedingung für gültige Befehle 3, 4 als wahr ausgewertet wird ).

Hier ist ein harmloses Beispiel:

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!

Das Zitieren Ihrer Variablen ist sicherer, z if "$var"; then. In den oben genannten Fällen sollten Sie eine Warnung erhalten, dass der Befehl nicht gefunden wird. Aber wir können es immer noch besser machen (siehe meine Empfehlungen unten).

Siehe auch Mike Holts Erklärung von Mikus ursprünglicher Antwort.

Probleme mit der Antwort von Hbar

Dieser Ansatz hat auch unerwartetes Verhalten.

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

# Outputs:
# This won't print, var is false!

Sie würden erwarten, dass die obige Bedingung als falsch ausgewertet wird, sodass die verschachtelte Anweisung niemals ausgeführt wird. Überraschung!

Das Zitieren des Werts ( "false"), das Zitieren der Variablen ( "$var") oder das Verwenden von testoder [[anstelle von [macht keinen Unterschied.

Was ich tun empfehlen:

Hier sind Möglichkeiten, wie ich Ihnen empfehlen kann, Ihre "Booleschen Werte" zu überprüfen. Sie arbeiten wie erwartet.

bool=true

if [ "$bool" = true ]; then
if [ "$bool" = "true" ]; then

if [[ "$bool" = true ]]; then
if [[ "$bool" = "true" ]]; then
if [[ "$bool" == true ]]; then
if [[ "$bool" == "true" ]]; then

if test "$bool" = true; then
if test "$bool" = "true"; then

Sie sind alle ziemlich gleichwertig. Sie müssen ein paar Tastenanschläge mehr eingeben als in den anderen Antworten 5 , aber Ihr Code ist defensiver.


Fußnoten

  1. Mikus Antwort wurde inzwischen bearbeitet und enthält keine (bekannten) Fehler mehr.
  2. Keine vollständige Liste.
  3. Ein gültiger Befehl bedeutet in diesem Zusammenhang einen vorhandenen Befehl. Es spielt keine Rolle, ob der Befehl richtig oder falsch verwendet wird. ZB man womanwürde immer noch als gültiger Befehl angesehen, selbst wenn keine solche Manpage existiert.
  4. Bei ungültigen (nicht vorhandenen) Befehlen beschwert sich Bash lediglich, dass der Befehl nicht gefunden wurde.
  5. Wenn Sie sich für die Länge interessieren, ist die erste Empfehlung die kürzeste.
Dennis
quelle
8
Verwendung ==mit [oder testnicht tragbar. In Anbetracht der Portabilität ist der einzige Vorteil [/ testhat gegenüber [[, bleiben Sie dabei =.
Chepper
2
@Scott Ich benutze Fisch als meine primäre Shell, die meiner Meinung nach eine vernünftige Skriptsprache im Vergleich zu Bash hat.
Dennis
1
Ja, ich konnte in den Kommentaren einfach keine Anerkennung für diesen versteckten Witz finden, also musste ich darauf hinweisen =)
Kranach
5
Konzeptionell ist es für mich einfacher zu verstehen, wenn ich bool = "true" verwende. Dann ist klar, dass es sich nur um eine Zeichenfolge handelt und nicht um einen speziellen Wert oder einen integrierten Wert.
wisbucky
1
@dolmen absolut, die Auswertung von Eingaben ist nicht so riskant, wenn Sie die Eingabe steuern, aber ich halte es dennoch für eine schlechte Praxis, die vermieden werden sollte, wenn sie leicht vermieden werden kann. Jemand, der den früheren Stil bisher nur gesehen und verwendet hat, weiß möglicherweise nichts über seine Mängel, die zu unerwartetem Verhalten führen können.
Dennis
175

Hier scheint es ein Missverständnis über das eingebaute Bash zu geben true, und insbesondere darüber, wie Bash Ausdrücke in Klammern erweitert und interpretiert.

Der Code in Mikus Antwort hat absolut nichts mit dem eingebauten Bash zu tun true, noch /bin/truemit irgendeiner anderen Variante des trueBefehls. In diesem Fall truehandelt es sich truelediglich um eine einfache Zeichenfolge, und es wird niemals ein Aufruf des Befehls / der eingebauten Datei vorgenommen, weder durch die Variablenzuweisung noch durch die Auswertung des bedingten Ausdrucks.

Der folgende Code ist funktional identisch mit dem Code in der Antwort des Mikus:

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

Der einzige Unterschied besteht darin, dass die vier verglichenen Zeichen 'y', 'e', ​​'a' und 'h' anstelle von 't', 'r', 'u' und 'e' sind. Das ist es. Es wird weder versucht, einen Befehl oder ein eingebautes Objekt mit dem Namen aufzurufen yeah, noch wird (in Mikus Beispiel) irgendeine spezielle Behandlung ausgeführt, wenn Bash das Token analysiert true. Es ist nur eine Saite und eine völlig willkürliche.

Update (2014-02-19): Nachdem ich dem Link in Mikus Antwort gefolgt bin, sehe ich jetzt, woher ein Teil der Verwirrung kommt. Mikus Antwort verwendet einzelne Klammern, aber das Code-Snippet, mit dem er verknüpft ist, verwendet keine Klammern. Es ist nur:

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

Beide Codefragmente verhalten sich gleich, aber die Klammern ändern vollständig, was unter der Haube vor sich geht.

Hier ist, was Bash in jedem Fall tut:

Keine Klammern:

  1. Erweitern Sie die Variable $the_world_is_flatauf die Zeichenfolge "true".
  2. Versuchen Sie, die Zeichenfolge "true"als Befehl zu analysieren .
  3. Suchen Sie den trueBefehl und führen Sie ihn aus (entweder integriert oder /bin/trueabhängig von der Bash-Version).
  4. Vergleichen Sie den Exit-Code des trueBefehls (der immer 0 ist) mit 0. Denken Sie daran, dass in den meisten Shells ein Exit-Code von 0 Erfolg anzeigt und alles andere einen Fehler anzeigt.
  5. Da der Exit-Code 0 (Erfolg) war, führen Sie die Klausel der ifAnweisung austhen

Klammern:

  1. Erweitern Sie die Variable $the_world_is_flatauf die Zeichenfolge "true".
  2. Analysieren Sie den jetzt vollständig erweiterten bedingten Ausdruck, der die Form hat string1 = string2. Der =Operator ist der String-Vergleichsoperator von bash . Damit...
  3. Führen Sie einen Zeichenfolgenvergleich für "true"und durch "true".
  4. Ja, die beiden Zeichenfolgen waren gleich, daher ist der Wert der Bedingung wahr.
  5. Führen Sie die Klausel der ifAnweisung aus then.

Der Code ohne Klammern funktioniert, da der trueBefehl einen Exit-Code von 0 zurückgibt, der den Erfolg anzeigt. Der Code in Klammern funktioniert, da der Wert von $the_world_is_flatmit dem Zeichenfolgenliteral trueauf der rechten Seite von identisch ist =.

Betrachten Sie die folgenden zwei Codeausschnitte, um den Punkt nach Hause zu bringen:

Dieser Code (wenn er mit Root-Rechten ausgeführt wird) startet Ihren Computer neu:

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

Dieser Code gibt nur "Netter Versuch" aus. Der Neustartbefehl wird nicht aufgerufen.

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

Update (14.04.2014) Um die Frage in den Kommentaren zum Unterschied zwischen =und ==: AFAIK zu beantworten , gibt es keinen Unterschied. Der ==Operator ist ein Bash-spezifisches Synonym für =und soweit ich gesehen habe, funktionieren sie in allen Kontexten genau gleich.

Beachten Sie jedoch, dass ich speziell über die Vergleichs- =und ==Zeichenfolgenvergleichsoperatoren spreche, die entweder in [ ]oder in [[ ]]Tests verwendet werden. Ich schlage das nicht vor =und bin überall in Bash ==austauschbar .

Zum Beispiel können Sie offensichtlich keine Variablenzuweisung durchführen ==, wie zum Beispiel var=="foo"(technisch gesehen können Sie dies tun, aber der Wert von varwird sein "=foo", da Bash hier keinen ==Operator sieht , sondern einen =(Zuweisungs-) Operator, gefolgt von der wörtliche Wert ="foo", der gerade wird "=foo").

Auch, obwohl =und ==untereinander austauschbar sind, sollten Sie bedenken , dass , wie diese Tests Arbeit nicht davon ab , ob Sie es innen mit sind [ ]oder [[ ]], und auch davon , ob oder nicht die Operanden angegeben. Weitere Informationen hierzu finden Sie im Advanced Bash Scripting Guide: 7.3 Andere Vergleichsoperatoren (scrollen Sie nach unten zur Diskussion von =und ==).

Mike Holt
quelle
Der No-Bracket-Ansatz hat auch den Vorteil, dass Sie saubere, klare (imo) Einzeiler wie$the_world_is_flat && echo "you are in flatland!"
ajk
9
Wahr. Obwohl ich mich nicht für (oder gegen) einen der beiden Ansätze ausspreche. Ich wollte nur einige der Fehlinformationen beseitigen, über die hier abgestimmt wird, damit Leute, die später über dieses Thema stolpern, nicht mit einer Reihe von Missverständnissen darüber davonkommen, wie das alles funktioniert.
Mike Holt
1
Der Grund für die Verwirrung ist, dass Mikus ursprüngliche Antwort 4 Jahre lang stand. Alle Verweise auf das eingebaute truewurden in Bezug auf die ursprüngliche Antwort gemacht. (Die überarbeitete Antwort am 12. Februar 2014 wurde nicht von miku eingereicht.) Ich habe die Antwort so bearbeitet, dass sie sowohl das Original als auch die überarbeitete enthält. Dann machen die Kommentare der Leute Sinn.
wisbucky
1
Durch das Lesen der hier angebotenen Antworten habe ich den Eindruck, dass es nicht möglich ist, das Reale tatsächlich zu verwenden true. Gibt es einen Weg? Ich vermute, dass viele Programmierer, die es gewohnt sind, diese Antworten strenger zu betrachten, um ihnen dabei zu helfen, etwas bashKleber zu mischen , um ihr Leben ein bisschen einfacher zu machen, einen ===Operator wünschen würden , damit Zeichenfolgen und "Boolesche Werte" nicht wirklich austauschbar sind. Sollten sie haften nur auf 0 und 1 und die Verwendung (( $maybeIAmTrue ))wie in vorgeschlagen Quolonel Frage ‚s Antwort ?
Selten Needy
2
Um den Kommentar von SeldomNeedy anzusprechen, können Sie das Real verwenden true, aber im Allgemeinen nicht als Vergleichsvariable, da das Real trueper se keinen Wert hat. Es wird lediglich der Exit-Status auf gesetzt 0, um den Erfolg anzuzeigen. Es ist erwähnenswert, dass es im Wesentlichen dem sogenannten "Null-Befehl" entspricht, oder :. Was die Verwendung von 0und 1angeht, mache ich das heutzutage in all meinen Skripten, in denen ich Boolesche Werte benötige. Und ich benutze den (( ))Operator anstatt [[ ]]zu bewerten. Also, wenn ich zum Beispiel habe flag=0, kann ich es dann tunif (( flag )); then ...
Mike Holt
57

Verwenden Sie arithmetische Ausdrücke.

#!/bin/bash

false=0
true=1

((false)) && echo false
((true)) && echo true
((!false)) && echo not false
((!true)) && echo not true

Ausgabe:

wahr
nicht falsch

Quolonel Fragen
quelle
3
Profis: (1.) Verhalten ist ähnlich wie Cs Umgang mit Bools, (2.) Syntax ist sehr präzise / minimal (erfordert keine rechte Variable und Operatoren wie '=' oder '=='), (3 .) <subjektiv> für mich verstehe ich, was ohne eine langwierige Erklärung passiert ... im Gegensatz zu den Antworten von Miku und Dennis, die beide langwierige Erklärungen erfordern </ subjektiv>
Trevor Boyd Smith
3
@TrevorBoydSmith Warum hast du nicht einfach gesagt: "Für: alles, Nachteile: nichts". Würde auf lange Sicht Abschreibungskosten auf Ihrer Tastatur und Ihrem Monitor sparen.
Quolonel Fragen
4
Stellen Sie für die interaktive Verwendung, wie z. B. Einzeiler, sicher, dass Sie ein Leerzeichen hinter sich lassen. Andernfalls !wird der Verlauf erweitert. ((! foo))funktioniert, so auch ! ((foo)). Ich liebe diese Lösung, übrigens. Endlich eine kurze Möglichkeit, boolesche Variablen zu erstellen. ((foo || bar))funktioniert wie erwartet.
Peter Cordes
5
(())erweitert Variablen rekursiv, was ich nicht erwartet hatte. foo=bar; bar=baz; ((foo)) && echo echodruckt nichts, aber es ist wahr mit baz=1. So können Sie foo=trueund foo=falsesowie 0 oder 1 unterstützen, indem Sie dies tun true=1.
Peter Cordes
2
@quolonel danke für die sehr hilfreiche Ressource. Natürlich ist mein Verständnis begrenzt - es liegt in der Natur des Menschen, in allem Verständnis unabhängig von der Domäne eingeschränkt zu sein. Würde es Ihnen jedoch etwas ausmachen, mir zu sagen, welche meiner Aussagen Sie zu der Annahme führen, dass mein Verständnis dieser speziellen Angelegenheit unvollständig ist?
Hubert Grzeskowiak
34

Um es kurz zu machen:

Es gibt keine Booleschen Werte in Bash

Bash hat boolesche Ausdrücke in Bezug auf Vergleich und Bedingungen. Was Sie in Bash deklarieren und vergleichen können, sind Zeichenfolgen und Zahlen. Das ist es.

Wo immer Sie es sehen trueoder falsein Bash, es ist entweder eine Zeichenfolge oder ein Befehl / eingebauter Befehl, der nur für den Exit-Code verwendet wird.

Diese Syntax ...

if true; then ...

Ist im Wesentlichen...

if COMMAND; then ...

Die Bedingung ist wahr , wenn der Befehl Exit - Code 0 trueund falseBash builtins sind und manchmal auch eigenständige Programme , die nichts tun , aber den entsprechenden Exit - Code zurück.

Die obige Bedingung entspricht:

COMMAND && ...

Wenn Sie eckige Klammern oder den testBefehl verwenden, verlassen Sie sich auf den Exit-Code dieses Konstrukts. Denken Sie daran [ ]und [[ ]]sind auch nur Befehle / eingebaute wie alle anderen. Damit ...

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

entspricht

if COMMAND; then echo yes; fi

und das COMMANDhier ist[[ 1 == 1 ]]

Das if..then..fiKonstrukt ist nur syntaktischer Zucker. Sie können die Befehle immer nur durch ein doppeltes kaufmännisches Und getrennt ausführen, um den gleichen Effekt zu erzielen:

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

Wenn Sie trueund falsein diesen Testkonstrukten verwenden, übergeben Sie tatsächlich nur die Zeichenfolge "true"oder "false"den Testbefehl. Hier ist ein Beispiel:

Ob Sie es glauben oder nicht, aber diese Bedingungen führen alle zum gleichen Ergebnis :

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

TL; DR; Vergleiche immer mit Strings oder Zahlen

Um dies zukünftigen Lesern klar zu machen, würde ich empfehlen, immer Anführungszeichen zu verwenden trueund false:

TUN

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

NICHT

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

Könnte sein

if [[ "${var}" != "true" ]]; then ...  # 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".
Hubert Grzeskowiak
quelle
Ich bevorzuge es zu verwenden Tund Fklar zu machen, dass dies keine echten booleschen Werte sind.
Phk
1
Ich kann nicht zustimmen mit "immer doppelte Klammern in Bash verwenden". Tatsächlich verwende ich in fast allen Skripten, die ich geschrieben habe, einzelne Klammern, außer wenn ich einen Mustervergleich durchführen muss. Ich denke, man sollte den Unterschied zwischen [(dh test) und dem verstehen, der [[für seine Bedürfnisse geeignet ist.
Weijun Zhou
@WeijunZhou Gedanken daran, in welchen Fällen einzelne Klammern besser sind?
Hubert Grzeskowiak
Es ist eher ein persönlicher Geschmack, ich finde es einfach zu kühn zu sagen "Verwenden Sie immer doppelte eckige Klammern in Bash". Aber es gibt einige Randfälle, die ich verwendet habe. In einzelnen Klammern können Sie den Test selbst in einer Variablen angeben. Betrachten if ....; then mytest='-gt'; else mytest='-eq'; fi; #several lines of code; if [ "$var1" "$mytest" "$var2" ]; then ...; fi
Sie
@WeijunZhou Ihr Beispiel ist ein starkes Argument gegen einzelne eckige Klammern. Es macht den Code viel schwieriger zu verstehen und öffnet das Fenster weit offen für Fehler. Doppelte Klammern sind strenger und fördern einen saubereren Code.
Hubert Grzeskowiak
18

Vor langer Zeit, als alles, was wir hatten sh, wurden Boolesche Werte verarbeitet, indem auf eine Konvention des testProgramms zurückgegriffen wurde, bei testder ein falscher Exit-Status zurückgegeben wird, wenn sie ohne Argumente ausgeführt werden.

Dies ermöglicht es einem, sich eine Variable vorzustellen, die nicht als falsch gesetzt ist, und eine Variable, die auf einen beliebigen Wert als wahr gesetzt ist. Heute testist es ein integrierter Bestandteil von Bash und allgemein bekannt unter seinem Alias ​​aus einem Zeichen [(oder einer ausführbaren Datei, die in Shells verwendet werden kann, in denen es fehlt, wie Dolmen bemerkt):

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

Aufgrund von Zitierkonventionen bevorzugen Skriptautoren den zusammengesetzten Befehl [[, der nachahmt test, aber eine schönere Syntax hat: Variablen mit Leerzeichen müssen nicht in Anführungszeichen gesetzt werden. Man kann &&und ||als logische Operatoren mit seltsamer Priorität verwenden, und es gibt keine POSIX-Einschränkungen für die Anzahl der Begriffe.

Um beispielsweise festzustellen, ob FLAG gesetzt ist und COUNT eine Zahl größer als 1 ist:

FLAG="u p"
COUNT=3

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

Dieses Zeug kann verwirrend werden, wenn Leerzeichen, Zeichenfolgen mit der Länge Null und Variablen mit dem Wert Null benötigt werden und auch wenn Ihr Skript mit mehreren Shells arbeiten muss.

Hbar
quelle
3
[ist nicht nur ein Alias ​​im Inneren bash. Dieser Alias ​​existiert auch als Binärdatei (oder als Link, auf den verwiesen wird) und kann mit dem Bare verwendet werden sh. Überprüfen Sie ls -l /usr/bin/\[. Mit bash/ zshsollten Sie stattdessen verwenden [[, das ist ein echtes reines Inneres und ist viel mächtiger.
Dolmen
1
@dolmen [und testist auch ein Bash SHELL BUILTIN COMMAND gemäß der Bash-Handbuchseite, daher sollte es kein Problem mit der Leistung geben. Gleiches gilt zB mit Dash. (/ bin / sh kann nur ein Symlink zu / bin / dash sein). Um die ausführbare Datei zu verwenden, müssen Sie den vollständigen Pfad verwenden, d /usr/bin/\[. H.
jarno
12

Wie kann ich boolesche Variablen in einem Shell-Skript deklarieren und verwenden?

Im Gegensatz zu vielen anderen Programmiersprachen trennt Bash seine Variablen nicht nach "Typ". [1]

Die Antwort ist also ziemlich klar. Es gibt keine boolesche Variable in Bash.

Jedoch:

Mit einer Deklarationsanweisung können wir die Wertzuweisung auf Variablen beschränken. [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"

Die rOption in declareund readonlywird verwendet, um explizit anzugeben, dass die Variablen schreibgeschützt sind . Ich hoffe, der Zweck ist klar.

sjsam
quelle
1
Warum tust du es nicht einfach declare -ir false=0 true=1? Was ist der Vorteil der Verwendung eines Arrays?
Benjamin W.
@ BenjaminW. Ich wollte nur die rOption und den readonlyBefehl erwähnen . Ich würde es so machen, wie Sie es in meinen Skripten vorgeschlagen haben
sjsam
Vielleicht habe ich etwas verpasst, aber warum nicht wahr und falsch auf diese Weise deklariert das Dollarzeichen verwenden? $ true $ false
Qodeninja
Ich kopiere buchstäblich nur meine Antwort und mache sie noch schlimmer.
Quolonel Fragen
@QuolonelQuestions Bash-Variablen werden nicht typisiert , daher macht es keinen Sinn zu sagen. declare and use boolean variablesWir könnten nur auf mehr als eine Weise nachahmen / annehmen, dass eine Variable einen Typ hat . Ich habe das nirgends in Ihrer Antwort erwähnt.
Sjsam
10

Warum nicht einfach einen besseren Wert als wahr und falsch verwenden, anstatt einen Booleschen Wert vorzutäuschen und zukünftigen Lesern eine Falle zu hinterlassen?

Zum Beispiel:

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
Pyrolistisch
quelle
warum nicht ganze Zahlen?
Phil294
3
@Blauhirn, weil Ganzzahlen je nach Sprache unterschiedlich verwendet werden. In einigen Sprachen 0zwingt zu falseund 1zu true. In Bezug auf Programm-Exit-Codes (die Bash historisch verwendet) ist es 0für ein positives Ergebnis oder trueund alles andere ist negativ / fehlerhaft oder false.
Hubert Grzeskowiak
7

POSIX (Portable Operating System Interface)

Ich vermisse hier den entscheidenden Punkt, nämlich die Portabilität. Deshalb hat mein Header POSIX an sich.

Im Wesentlichen sind alle abgestimmten Antworten korrekt, mit der Ausnahme, dass sie zu viel Bash- spezifisch sind.

Grundsätzlich möchte ich nur weitere Informationen zur Portabilität hinzufügen.


  1. [und ]Klammern wie in [ "$var" = true ]sind nicht erforderlich, und Sie können sie weglassen und den testBefehl direkt verwenden:

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

    Wichtiger Hinweis: Ich empfehle dies nicht mehr, da es langsam veraltet ist und es schwieriger ist, mehrere Anweisungen zu kombinieren.

  2. Stellen Sie sich vor , was diese Worte trueund falsebedeuten mit der Schale, testen Sie es selbst:

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

    Aber mit Anführungszeichen:

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

    Das gleiche gilt für:

    echo $(( "false" ))

    Die Shell kann es nur als Zeichenfolge interpretieren. Ich hoffe, Sie bekommen eine Vorstellung davon, wie gut es ist, das richtige Schlüsselwort ohne Anführungszeichen zu verwenden .

    Aber niemand hat es in früheren Antworten gesagt.

  3. Was bedeutet das? Nun, mehrere Dinge.

    • Sie sollten sich daran gewöhnen, dass boolesche Schlüsselwörter tatsächlich wie Zahlen behandelt werden, dh true= 0und false= 1. Denken Sie daran, dass alle Werte ungleich Null wie behandelt werden false.

    • Da sie als Zahlen behandelt werden, sollten Sie sie auch so behandeln, dh wenn Sie eine Variable definieren, sagen Sie:

      var_bool=true
      echo "$var_bool"
       true

      Sie können einen entgegengesetzten Wert davon erstellen mit:

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

    Wie Sie selbst sehen können, druckt die Shell truezum ersten Mal eine Zeichenfolge, aber seitdem funktioniert alles über eine Zahl, die 0darstellt truebzw. 1darstellt false.


Schließlich, was Sie mit all diesen Informationen tun sollten

  • Erstens wäre eine gute Angewohnheit, 0statt zuzuweisen true; 1statt false.

  • Die zweite gute Angewohnheit wäre zu testen, ob die Variable gleich Null ist / nicht:

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

In Bezug auf die Syntax ist dies eine einfache Methode, die ich (anhand eines Beispiels) verwende, um die Boolesche Logik konsistent und vernünftig zu verwalten:

# 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

Wenn die Variable niemals deklariert wird, lautet die Antwort: # false

So ist eine einfache Möglichkeit , eine Variable auf true (unter Verwendung dieser Syntax Methodik) zu setzen wäre, var=1; umgekehrt var=''.

Referenz:

-n = True, wenn die Länge der var-Zeichenfolge ungleich Null ist.

-z = True, wenn die Länge der var-Zeichenfolge Null ist.

Eric P.
quelle
5

In vielen Programmiersprachen ist oder wird der Boolesche Typ als Subtyp einer Ganzzahl implementiert, wobei truesich Folgendes verhält 1und falsewie folgt verhält 0:

Mathematisch ähnelt die Boolesche Algebra dem ganzzahligen arithmetischen Modulo 2. Wenn eine Sprache keinen nativen Booleschen Typ bietet, ist die natürlichste und effizienteste Lösung die Verwendung von Ganzzahlen. Dies funktioniert mit fast jeder Sprache. In Bash können Sie beispielsweise Folgendes tun:

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

Mann Bash :

((Ausdruck))

Der Ausdruck wird gemäß den unten unter ARITHMETISCHE BEWERTUNG beschriebenen Regeln bewertet. Wenn der Wert des Ausdrucks nicht Null ist, ist der Rückgabestatus 0; Andernfalls lautet der Rückgabestatus 1. Dies entspricht genau dem Ausdruck "Ausdruck".

Cyker
quelle
5

Bill Parker wird abgewählt , weil seine Definitionen von der normalen Code-Konvention umgekehrt sind. Normalerweise ist true als 0 und false als ungleich Null definiert. 1 funktioniert für false, ebenso wie 9999 und -1. Das Gleiche gilt für Funktionsrückgabewerte - 0 ist erfolgreich und alles, was nicht Null ist, ist ein Fehler. Entschuldigung, ich habe noch nicht die Glaubwürdigkeit, auf der Straße abzustimmen oder ihm direkt zu antworten.

Bash empfiehlt, Doppelklammern jetzt als Gewohnheit anstelle von Einzelklammern zu verwenden, und der Link, den Mike Holt gab, erklärt die Unterschiede in ihrer Funktionsweise. 7.3. Andere Vergleichsoperatoren

Zum einen -eqist ein numerischer Operator also der Code

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

gibt eine Fehleranweisung aus und erwartet einen ganzzahligen Ausdruck. Dies gilt für beide Parameter, da keiner ein ganzzahliger Wert ist. Wenn wir jedoch doppelte Klammern setzen, wird keine Fehleranweisung ausgegeben, aber es wird ein falscher Wert ausgegeben (also in 50% der möglichen Permutationen). Es wird zu [[0 -eq true]] = Erfolg ausgewertet, aber auch zu [[0 -eq false]] = Erfolg, was falsch ist (hmmm .... was ist mit diesem eingebauten Wert?).

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

Es gibt andere Permutationen der Bedingung, die ebenfalls eine falsche Ausgabe ergeben. Grundsätzlich alles (außer der oben aufgeführten Fehlerbedingung), das eine Variable auf einen numerischen Wert setzt und sie mit einem True / False-Builtin vergleicht oder eine Variable auf ein True / False-Builtin setzt und sie mit einem numerischen Wert vergleicht. Auch alles, was eine Variable auf ein True / False-Builtin setzt und einen Vergleich mit -eq. Vermeiden Sie daher -eqboolesche Vergleiche und vermeiden Sie die Verwendung numerischer Werte für boolesche Vergleiche. Hier ist eine Zusammenfassung der Permutationen, die zu ungültigen Ergebnissen führen:

# 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

Also nun zu dem, was funktioniert. Verwenden Sie True / False-Buildins sowohl für Ihren Vergleich als auch für Ihre Bewertungen (wie Mike Hunt feststellte, schließen Sie sie nicht in Anführungszeichen ein). Verwenden Sie dann entweder ein oder doppeltes Gleichheitszeichen (= oder ==) und entweder einfache oder doppelte Klammern ([] oder [[]]). Persönlich mag ich das doppelte Gleichheitszeichen, weil es mich an logische Vergleiche in anderen Programmiersprachen erinnert, und doppelte Anführungszeichen, nur weil ich gerne tippe. Also diese Arbeit:

# 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

Hier hast du es.

Randyman99
quelle
2
Die true/ falseintegrierten Funktionen werden hier nicht verwendet (ignorieren Sie, was die Syntaxhervorhebung einiger Editoren möglicherweise impliziert), insbesondere in den […]Fällen , in denen Sie sie hier als einfache Zeichenfolge betrachten können (eine, die als Parameter für den [Befehl angegeben wird).
Phk
Du hast es jetzt.
Peter Mortensen
4

Meine Ergebnisse und Vorschläge unterscheiden sich ein wenig von den anderen Beiträgen. Ich fand heraus, dass ich "Boolesche Werte" grundsätzlich wie in jeder "normalen" Sprache verwenden könnte, ohne dass das "Reifenspringen" vorgeschlagen würde ...

Es sind keine []expliziten Zeichenfolgenvergleiche erforderlich oder explizit ... Ich habe mehrere Linux-Distributionen ausprobiert. Ich habe Bash, Dash und BusyBox getestet . Die Ergebnisse waren immer gleich. Ich bin mir nicht sicher, worüber die ursprünglichen Beiträge mit den höchsten Stimmen sprechen. Vielleicht haben sich die Zeiten geändert und das ist alles, was dazu gehört?

Wenn Sie eine Variable auf setzen true, wird diese anschließend innerhalb einer Bedingung als "positiv" ausgewertet. Setzen Sie es auf falseund es wird als "negativ" ausgewertet. Sehr einfach! Die einzige Einschränkung ist, dass eine undefinierte Variable ebenfalls als wahr ausgewertet wird ! Es wäre schön, wenn es das Gegenteil tun würde (wie es in den meisten Sprachen der Fall wäre), aber das ist der Trick - Sie müssen nur Ihre Booleschen Werte explizit auf wahr oder falsch initialisieren .

Warum funktioniert das so? Diese Antwort ist zweifach. A) wahr / falsch in einer Shell bedeutet wirklich "kein Fehler" gegen "Fehler" (dh 0 gegen alles andere). B) wahr / falsch sind keine Werte - sondern Aussagen im Shell-Scripting! In Bezug auf den zweiten Punkt setzt das Ausführen trueoder falsein einer Zeile für sich den Rückgabewert für den Block, in dem Sie sich befinden, auf diesen Wert, dh falseeine Deklaration von "Fehler aufgetreten", wobei true dies "löscht". Wenn Sie es mit einer Zuordnung zu einer Variablen verwenden, wird dies in die Variable "zurückgegeben". Eine undefinierte Variable wird wie truein einer Bedingung ausgewertet , da dies gleichermaßen 0 oder "kein Fehler aufgetreten" darstellt.

Siehe das Beispiel Bash-Linien und Ergebnisse unten. Testen Sie es selbst, wenn Sie bestätigen möchten ...

#!/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;

Erträge

when set to
it evaluates to true
when set to true
it evaluates to true
when set to false
it evaluates to false
BuvinJ
quelle
1

Hier ist ein einfaches Beispiel, das für mich funktioniert:

temp1=true
temp2=false

if [ "$temp1" = true ] || [ "$temp2" = true ]
then
    echo "Do something." 
else
    echo "Do something else."
fi
Harsimranjit Singh Kler
quelle
1

Hier ist eine Implementierung eines Shorthanded 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
}

Beispiel 1

my_boolean=true

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

Beispiel 2

my_boolean=false
! _if ${my_boolean} && echo "Not True is True"
llundin
quelle
Ja, funktionelle Zersetzung wird unterschätzt.
Peter Mortensen
1

Ich fand die vorhandenen Antworten verwirrend.

Persönlich möchte ich nur etwas haben, das aussieht und funktioniert wie C.

Dieses Snippet funktioniert mehrmals täglich in der Produktion:

snapshotEvents=true

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

und um alle glücklich zu machen, habe ich getestet:

snapshotEvents=false

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

Was auch gut funktioniert hat.

Das $snapshotEventswertet den Wertinhalt der Variablen aus. Also brauchst du das $.

Sie brauchen die Klammern nicht wirklich, ich finde sie nur hilfreich.

werden
quelle
2
Wenn Sie die Klammern entfernen, ist dies genau die ursprüngliche Antwort von @ miku oben.
Dolmen
1
Ohne Klammern wird der Ausdruck nicht ausgewertet.
wird
@ wird ja das tut es. Sie brauchen die () s nicht.
Phil294
1
@Blauhirn ... Hallo, ich habe meine Kommentare auf Experimenten mit GNU Bash auf einem Linux Mint / Ubuntu-PC basiert. Sie haben wahrscheinlich Recht in der Theorie () - sie werden nicht benötigt. Meine einzige Antwort ist, es auszuprobieren, es scheint von der Bash-Version, dem tatsächlichen Ausdruck oder Kontext und so weiter abzuhängen .
wird
1

Hier ist eine Verbesserung gegenüber Mikus ursprünglicher Antwort , die Dennis Williamsons Bedenken in Bezug auf den Fall anspricht, in dem die Variable nicht festgelegt ist:

the_world_is_flat=true

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

Und um zu testen, ob die Variable ist false:

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

In anderen Fällen mit einem unangenehmen Inhalt in der Variablen ist dies ein Problem mit externen Eingaben, die einem Programm zugeführt werden.

Alle externen Eingaben müssen vor dem Vertrauen validiert werden. Diese Validierung muss jedoch nur einmal durchgeführt werden, wenn diese Eingabe empfangen wird.

Es muss sich nicht auf die Leistung des Programms auswirken, indem es bei jeder Verwendung der Variablen ausgeführt wird, wie Dennis Williamson vorschlägt.

Dolmen
quelle
1

Sie können shFlags verwenden .

Sie haben die Möglichkeit zu definieren: DEFINE_bool

Beispiel:

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

Über die Befehlszeile können Sie Folgendes definieren:

sh script.sh --bigmenu
sh script.sh --nobigmenu # False
Gogasca
quelle
GFlags macht in dieser Antwort keinen Sinn - es ist eine C ++ - Bibliothek. Es kann nicht direkt in Shell-Skripten verwendet werden.
Jonathan Cross
Aktualisierte Antwort auf shFlags, einen Port von GFlags zur Shell.
Gogasca
0

Dies ist ein Geschwindigkeitstest über verschiedene Möglichkeiten zum Testen von "Booleschen" Werten in Bash:

#!/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

Es würde so etwas wie drucken

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
jarno
quelle
-2

Alternative - benutze eine Funktion

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

Das Definieren der Funktion ist weniger intuitiv, aber das Überprüfen des Rückgabewerts ist sehr einfach.

Johnraff
quelle
1
Dies ist keine Variable, die Sie testen könnten, sondern eine konstante Funktion
jarno
@jarno Unterscheidet sich das Testen des Rückgabewerts einer Funktion vom Testen einer Variablen für die Zwecke eines Skripts?
Johnraff
Nun, die Frage betrifft Variablen.
Jarno
Richtig, obwohl die Verwendung in einem Shell-Skript dieselbe wäre.
Johnraff
-2

Bash verwirrt wirklich das Problem mit Größen wie [, [[, ((, $((etc.

Alle treten auf die Codebereiche der anderen. Ich denke, das ist größtenteils historisch, wo Bash vorgeben musste, shgelegentlich zu sein.

Meistens kann ich einfach eine Methode auswählen und dabei bleiben. In diesem Fall neige ich dazu, zu deklarieren (vorzugsweise in einer allgemeinen Bibliotheksdatei, die ich .in meine eigentlichen Skripte aufnehmen kann).

TRUE=1; FALSE=0

Ich kann dann den ((... ))arithmetischen Operator verwenden, um auf diese Weise zu testen.

testvar=$FALSE

if [[ -d ${does_directory_exist} ]]
then
    testvar=$TRUE;
fi

if (( testvar == TRUE )); then
    # Do stuff because the directory does exist
fi
  1. Du musst diszipliniert sein. Sie testvarmüssen entweder auf $TRUEoder $FALSEjederzeit eingestellt sein.

  2. In ((... ))Komparatoren benötigen Sie das Vorhergehende nicht $, wodurch es besser lesbar ist.

  3. Ich kann ((... verwenden, ))weil $TRUE=1und $FALSE=0, dh numerische Werte.

  4. Der Nachteil ist, dass Sie $gelegentlich Folgendes verwenden müssen :

    testvar=$TRUE

    das ist nicht so hübsch.

Es ist keine perfekte Lösung, aber es deckt jeden Fall ab, den ich für einen solchen Test benötige.

Bill Parker
quelle
2
Sie sollten Ihre Konstanten schreibgeschützt deklarieren. Verwenden Sie bei der Verwendung von Variablen auch immer geschweifte Klammern. Es ist eine Konvention, an die sich jeder halten sollte. Der große Nachteil dieser Lösung ist, dass Sie den algebraischen Ausdruck nicht mit Testflags oder Zeichenfolgenvergleichen mischen können.
Hubert Grzeskowiak