Ich möchte ein einfaches Skript ausprobieren
flag=false
while !$flag
do
read x
if [ "$x" -eq "true" ]
then
flag=true
fi
echo "${x} : ${flag}"
done
Aber wenn ich es laufen lasse, wenn ich tippe true
, sehe ich das x="true"
und flag="true"
, aber der Zyklus endet nicht. Was ist los mit dem Skript? Wie kann ich eine boolesche Variable richtig invertieren?
Antworten:
Es gibt zwei Fehler in Ihrem Skript. Das erste ist, dass Sie ein Leerzeichen zwischen
!
und benötigen$flag
, andernfalls sucht die Shell nach einem aufgerufenen Befehl!$flag
. Der zweite Fehler-eq
betrifft Ganzzahlvergleiche, aber Sie verwenden ihn für eine Zeichenfolge. Abhängig von Ihrer Shell wird entweder eine Fehlermeldung angezeigt und die Schleife für immer fortgesetzt, da die Bedingung[ "$x" -eq "true" ]
nicht wahr sein kann, oder jeder nicht ganzzahlige Wert wird als 0 behandelt und die Schleife wird beendet, wenn Sie eine Zeichenfolge (einschließlichfalse
) eingeben. anders als eine Zahl von 0.Solange
! $flag
es richtig ist, ist es eine schlechte Idee, eine Zeichenfolge als Befehl zu behandeln. Es würde funktionieren, wäre aber sehr empfindlich gegenüber Änderungen in Ihrem Skript, da Sie sicherstellen müssten, dass$flag
dies niemals etwas anderes alstrue
oder sein kannfalse
. Es wäre besser, hier einen Zeichenfolgenvergleich zu verwenden, wie im folgenden Test.Es gibt wahrscheinlich eine bessere Möglichkeit, die Logik auszudrücken, nach der Sie suchen. Beispielsweise können Sie eine Endlosschleife erstellen und diese unterbrechen, wenn Sie die Beendigungsbedingung erkennen.
quelle
[
eingebauten Wert vonksh
wird[ x -eq y ]
true zurückgegeben, wenn derx
arithmetische Ausdruck in dieselbe Zahl aufgelöst wird wie dery
arithmetische Ausdruck, sodass beispielsweisex=2 true=1+1 ksh -c '[ x -eq true ] && echo yes'
yes ausgegeben wird.Während es in Bash keine Booleschen Variablen gibt, ist es sehr einfach, sie mithilfe der arithmetischen Auswertung zu emulieren.
Dies funktioniert auch in ksh. Es würde mich nicht wundern, wenn es in allen POSIX-kompatiblen Shells funktioniert, aber den Standard nicht überprüft hat.
quelle
! ! ((val))
in Bash wie in C oder C ++? Wenn zum Beispielval
0 ist, bleibt es danach 0! !
. Wennval
1 ist, bleibt es 1 danach! !
. Wennval
8 ist, wird es danach auf 1 heruntergezogen! !
. Oder muss ich eine andere Frage stellen?Wenn Sie absolut sicher sind, dass die Variable entweder 0 oder 1 enthält, können Sie mit dem bitweisen XOR-Gleichheitsoperator zwischen den beiden Werten wechseln:
quelle
Das funktioniert bei mir:
Aber eigentlich sollten Sie Ihre ersetzen
while
durch:quelle
Es gibt kein Konzept für eine Boolesche Variable in der Shell.
Shell - Variablen könnten nur sein
text
(eine Zeichenfolge), und in einigen Fällen, dass Text als Integer interpretiert werden (1
,0xa
,010
, etc.).Daher
flag=true
impliziert a überhaupt keine Wahrhaftigkeit oder Falschheit der Hülle.String
Sie können entweder einen Zeichenfolgenvergleich durchführen
[ "$flag" == "true" ]
oder den Variableninhalt in einem Befehl verwenden und dessen Konsequenzen überprüfen , z. B. "execute"true
(da sowohl eine ausführbare als auchtrue
eine aufgerufene Datei vorhanden istfalse
) als Befehl und prüfen, ob der Beendigungscode dieses Befehls Null ist (erfolgreich).Oder kürzer:
Wenn der Inhalt einer Variablen als Befehl verwendet wird, kann a
!
verwendet werden, um den Beendigungsstatus des Befehls zu negieren, wenn zwischen both (! cmd
) ein Leerzeichen vorhanden ist , wie in:Das Skript sollte folgendermaßen geändert werden:
Ganze Zahl
Verwenden Sie numerische Werte und arithmetische Erweiterungen .
In diesem Fall sind der Exit-Code von
$((0))
is1
und der Exit-Code von$((1))
is0
.In bash, ksh und zsh könnte die Arithmetik innerhalb von a ausgeführt werden
((..))
(beachten Sie, dass der Anfang$
fehlt).flag=0; if ((flag)); then ... fi
Eine portable Version dieses Codes ist komplizierter:
In bash / ksh / zsh können Sie Folgendes tun:
Alternative
Sie können "eine boolesche Variable invertieren" (vorausgesetzt, sie enthält einen numerischen Wert) als:
((flag=!flag))
Das ändert den Wert von
flag
entweder0
oder1
.Hinweis : Überprüfen Sie https://www.shellcheck.net/ auf Fehler, bevor Sie Ihren Code als Frage veröffentlichen. Dies ist oft genug, um das Problem zu finden.
quelle
until
ist die Abkürzung fürwhile !
(unduntil
im Gegensatz zu!
Bourne), so dass Sie Folgendes tun können:Welches sollte das gleiche sein wie:
Sie könnten es auch schreiben als:
Der Teil zwischen
until
/while
unddo
muss kein einzelner Befehl sein.!
ist ein Schlüsselwort in der POSIX-Shell-Syntax. Es muss abgegrenzt sein, ein von dem Folgenden getrenntes Token und das erste Token, das einer Pipeline vorausgeht (! foo | bar
negiert die Pipeline undfoo | ! bar
ist ungültig, obwohl einige Shells sie als Erweiterung akzeptieren).!true
wird als der!true
Befehl interpretiert , dessen Existenz unwahrscheinlich ist.! true
sollte arbeiten.!(true)
sollte in POSIX-kompatiblen Shells funktionieren!
, da dies durch ein(
Token abgegrenzt ist. In der Praxis funktioniert es jedoch nicht inksh
/bash -O extglob
wo es mit dem!(pattern)
erweiterten Glob-Operator oder zsh (außer in der Sh-Emulation) in Konflikt steht, wo esglob(qualifiers)
mitbareglobqual
und in Konflikt stehtglob(group)
ohne.quelle
oder auch:
sollte den Job machen
quelle