Was ist eine bewährte Methode, um einen Booleschen Wert in einem Shell-Skript darzustellen?

15

Ich weiß, dass es boolesche Werte gibt bash, aber ich sehe sie nirgendwo verwendet.

Ich möchte einen Wrapper für einige häufig nachgeschlagene Informationen auf meinem Computer schreiben, zum Beispiel ist dieses spezielle USB-Laufwerk eingesteckt / montiert.

Was wäre die beste Vorgehensweise, um dies zu erreichen?

  • Ein Faden?

    drive_xyz_available=true
  • Eine Zahl (0 für wahr, 0 für falsch)?

    drive_xyz_available=0    # evaluates to true
  • Eine Funktion?

    drive_xyz_available() { 
        if available_magic; then 
                return 0 
        else 
                return 1 
        fi
    }
    

Ich frage mich meistens, was andere Leute von dem Wrapper erwarten würden. Würden sie einen booleschen Wert, einen Befehl wie eine Variable oder eine Funktion zum Aufrufen erwarten?

Unter Sicherheitsaspekten würde ich die zweite Option für die sicherste halten, aber ich würde gerne Ihre Erfahrungen hören.

Minix
quelle
3
help true ; help false ; help exit
Costas
3
@Costas Würde es Ihnen etwas ausmachen, näher darauf einzugehen?
Minix

Antworten:

2
bool(){ return "$((!${#1}))"; }

if bool "$var"
then : do true
else : do false

Setzen Sie einfach eine Variable auf einen Wert, der nicht null ist, damit das oben Genannte funktioniert. Dies [ -n "$var" ]wäre jedoch kürzer, wenn nicht sogar so offensichtlich.

Wenn ein Skript eine Umgebungsvariable als wahr oder falsch interpretiert, interpretiert es einen Wert im Allgemeinen als wahr (und verwendet diesen Wert manchmal, um eine Option zu konfigurieren) oder einen Nullwert als falsch.

Der obige !notWert gibt den Booleschen Wert der Länge des ersten Arguments zurück. Wenn das Argument eine beliebige Anzahl von Zeichen außer 0 enthält, gibt es 0 zurück. Wenn überhaupt keine Zeichen vorhanden sind, wird 1 zurückgegeben. Dies ist im [ -n "$var" ]Grunde derselbe Test, den Sie durchführen können , aber es hüllt es einfach in eine kleine Funktion namens bool().

So funktioniert normalerweise eine Flag- Variable. Beispielsweise:

[ -d "$dir" ] || dir=

Wo andere Teile eines Skripts nur nach einem Wert suchen müssen, um $dirseine Nützlichkeit zu beurteilen. Dies ist auch praktisch, wenn es um die Ersetzung von Parametern geht - da Parameter auf Standardwerte erweitert werden können, um leere oder nicht gesetzte Werte einzufügen, aber ansonsten auf einen voreingestellten Wert wie ...

for set in yes ''
do echo "${set:-unset or null}"
done

... was würde drucken ...

yes
unset or null

Natürlich ist es auch möglich, das Gegenteil zu tun, :+aber das kann Ihnen immer nur einen voreingestellten Standardwert oder gar nichts geben, wohingegen das obige Formular Ihnen einen Wert oder einen Standardwert geben kann.

In Bezug auf die drei Optionen kann jede davon funktionieren, je nachdem, wie Sie sie implementieren. Die Rückgabe der Funktion ist ein Selbsttest, aber wenn diese Rückgabe aus irgendeinem Grund gespeichert werden muss, muss sie in eine Variable eingefügt werden. Es kommt auf den Anwendungsfall an - ist der Boolesche Wert, den Sie einmal auswerten möchten, und geben Sie ihn ein? Wenn ja, machen Sie die Funktion, sonst ist wahrscheinlich eine der beiden anderen notwendig.

mikeserv
quelle
1
Ich glaube nicht, dass du meine Frage beantwortest. Ich frage nicht, wie Boolesche Werte in einem Shell-Skript verwendet werden könnten, sondern wie sie am häufigsten verwendet werden und wie sie von einem anderen Benutzer erwartet werden. Wenn meine Frage unklar ist, bearbeite ich sie gerne. Auch eine kurze Erklärung, was Ihre Antwort tut, wäre nett. Vielen Dank.
Minix
@Minix Geht es dir besser?
mikeserv
Ich ordne im Allgemeinen trueoder falseeiner Variablen zu, die Sie dann tun könnenif $variable; then ...
Wurtel
@wurtel - das setzt default voraus - $IFSund wenn der var-Wert Benutzereingaben jeglicher Art enthalten könnte, dann auch viel Glück. Wenn der Wert zunächst nicht unbekannt ist, muss er kaum getestet werden. Sicherer können Sie if ${var:+":"} false; thenbei der Arbeit mit booleschen Null- / Nicht-Null-Werten vorgehen. Aber das ist selten nützlicher als[ -n "$var" ] &&
mikeserv
Wenn ich mein Skript mit starte variable=falseund es dann je nach den Bedingungen auf true setze (genau wie bei Verwendung einer Variablen in C), gibt es überhaupt kein Problem. Was ist Ihre Besessenheit, wenn Sie IFS-Werte, Zufallsvariablen usw. variieren? .
wurtel
4

In bashjeder Variablen ist im Wesentlichen eine Zeichenfolge (oder ein Array oder eine Funktion, aber lassen Sie uns hier über reguläre Variablen sprechen).

Die Bedingungen werden basierend auf den Rückgabewerten der Testbefehle analysiert - der Rückgabewert ist keine Variable, sondern ein Exit-Status. Wenn Sie if [ ... ]oder if [[ ]]oder if grep somethingoder so etwas auswerten , bedeutet der Rückgabewert 0 (nicht Zeichenfolge 0, sondern Beendigungsstatus 0 = Erfolg) wahr und der Rest falsch (also genau das Gegenteil von dem, was Sie in kompilierten Programmiersprachen gewohnt sind). Da es jedoch eine Möglichkeit zum Erfolg und viele Möglichkeiten zum Fehlschlagen gibt und das erwartete Ergebnis der Ausführung in der Regel ein Erfolg ist, wird 0 als häufigstes Standardergebnis verwendet, wenn nichts schief geht. Dies ist sehr nützlich, da jede Binärdatei als Test verwendet werden kann. Wenn sie fehlschlägt, ist sie falsch, andernfalls ist sie wahr.

trueund falseProgramme (in der Regel von eingebauten Programmen überschrieben) sind nur nützliche kleine Programme, die nichts truetun. Sie können nichts falsetun und beenden mit 0, während sie versuchen, nichts zu tun und mit 1 "fehlschlagen".

Es liegt an Ihnen, wie Sie Wahrhaftigkeit weitergeben. Es ist durchaus üblich, nur "y" oder "yes" für Wahrheit und Verwendung zu verwenden if [ x"$variable" = x"yes" ](fügte die Dummy-Zeichenfolge hinzu, xda $variabledies vor der Erstellung eines falschen Befehls if [ = "yes" ]schützt, der nicht analysiert wird, wenn die Länge Null ist ). Es kann auch nützlich sein, einfach eine leere Zeichenfolge für false zu verwenden und [ -z "$variable ]zu testen, ob sie eine Länge von Null hat (oder -nnicht Null ist).

Wie auch immer, es ist ziemlich selten, dass tatsächlich boolesche Werte übergeben werden müssen bash- es ist viel häufiger, einfach einen exitFehler zu melden oder ein nützliches Ergebnis zurückzugeben (oder Null, wenn etwas schief geht und auf leere Zeichenfolgen zu testen), und die meisten Fälle können dies Direkt vom Ausgangsstatus auf Fehler prüfen.


In Ihrem Fall möchten Sie eine Funktion, die wie jeder andere Befehl funktioniert (daher bei Erfolg 0 zurückgeben), sodass Ihre letzte Option die richtige Wahl zu sein scheint.

Außerdem brauchen Sie möglicherweise nicht einmal eine returnErklärung. Wenn die Funktion einfach genug ist, können Sie die Tatsache verwenden, dass sie einfach den Status des zuletzt ausgeführten Befehls in der Funktion zurückgibt. So kann Ihre Funktion einfach sein

drive_xyz_available() {
   [ -e /dev/disk/by-uuid/whatever ]
}

Wenn Sie auf das Vorhandensein eines Geräteknotens /proc/mountsprüfen (oder nachfragen , ob dieser eingehängt ist?).

orion
quelle
Das ist eine sehr schöne Zusammenfassung. Vielen Dank, dass Sie sich die Zeit genommen haben, sie aufzuschreiben. Kann ich aus Ihrem letzten Absatz schließen, dass Sie die Option drive_xyz_available()als die häufigste betrachten würden?
Minix
Können Sie einige Beispiele für den allgemeinen y = trueFall nennen? Nach meiner Erfahrung prüfen die meisten Wrapper-Skripte, ob ein Wert ungleich Null vorliegt, um ihn als wahr zu betrachten - zumindest, wenn es um interpretierte Umgebungsvariablen geht. Ansonsten ignorieren sie Muschelautos.
mikeserv
3
Die Dummy-Zeichenfolge für den ifTest ist nicht erforderlich, wenn die Variable in Anführungszeichen gesetzt ist. if [ "$variable" = "yes" ]funktioniert einwandfrei, auch wenn $ variable nicht gesetzt ist.
Daniel Kullmann
-2

Grundsätzlich ist jede Zahl, die nicht 0 ist, wahr und 0 ist falsch. Grund für die Rückgabe von 0 für ein erfolgreiches Ende eines Skripts oder einer anderen Zahl, um verschiedene Arten von Fehlern zu identifizieren.

$? Gibt den Exit-Code des vorherigen Befehls / der vorherigen ausführbaren Datei zurück, wobei 0 Erfolg hat, und jede andere Zahl den zurückgegebenen Fehler.

Also würde ich diese Methode für wahr / falsch verwenden. if (( ! $? ));then OK;else NOOK;fi

YoMismo
quelle
Ich werde dann eine für die letzte Option aufschreiben. Vielen Dank.
Minix
5
Eine Zahl ungleich Null ist tatsächlich falsch und Null ist wahr. Schauen Sie sich die Ausgabe von true; echo $?und an false; echo $?.
Ruslan
@ Ruslan. Haben Sie die Ausgabe meines Befehls überprüft? Ich denke, du hast es nicht getan, sonst hättest du nicht gesagt, was du getan hast. 0 ist falsch, jede andere Zahl ist wahr, Grund, !das Ergebnis zu negieren , damit es WAHR ist. Das Ergebnis eines Befehls ist 0, wenn es korrekt beendet wurde, was nicht bedeutet, dass 0 wahr ist. Das Wort truekann 0 sein, aber 0 ist niemals wahr, wie die ifBedingung zeigt.
YoMismo
Das ist das gleiche wie zu sagen , dass in C / C ++, 0ist trueda if(!x){True();}else{False();}rufen , True()wenn x==0. Die richtige Prüfung wäre aber nicht !x, sondern !!x.
Ruslan
Du liegst falsch. Ich spreche nicht darüber, was und welche Reihenfolge hat, was Sie schreiben, nachdem ifich nur die Tatsache angegeben habe, dass hier (in bash oder ksh oder tsh oder ....) wie in C / C ++ eine 0 FALSCH ist Die andere Zahl ist WAHR, wie Sie im folgenden Link nachlesen können. Erste Implementierungen von C lieferten keinen Booleschen Typ. Sie wurden als ints definiert, wobei 0 FALSCH und 1 WAHR war. en.wikipedia.org/wiki/Boolean_data_type .
YoMismo