Die GNU-Bash-Manpage für [[..]]
erklärt, dass der Operator einen bedingten Ausdruck ausführt und
Gibt einen Status von 0
zurück oder 1
abhängig von der Auswertung des bedingten Ausdrucks expression
. Ausdrücke bestehen aus den Primärwörtern, die unten in Bedingte Bash-Ausdrücke beschrieben werden.
Aber der arithmetische Operator ist nicht Teil der unterstützten bedingten Ausdrücke (primaries ) in [[..]]
was bedeutet, dass der Ausdruck gezwungen wird, als Zeichenfolgenvergleich ausgeführt zu werden, d. h.
(( $n < 3))
wird nicht im arithmetischen Kontext ausgeführt aber genauso einfacher lexikografischer (String-)Vergleich wie
[[ 100 < 3 ]]
was immer wahr ergibt, weil die ASCII-Werte für 1
, 0
, 0
vor 3
erscheinen
Aber innerhalb von [[..]]
arithmetische Operationen werden unterstützt, wenn Sie -lt
verwenden , -gt
arg1 OP arg2
OP ist einer von -eq
, -ne
, -lt
, -le
, -gt
, oder -ge
. Diese arithmetischen binären Operatoren geben wahr zurück, wenn arg1
ist gleich, ungleich, kleiner als, kleiner oder gleich, größer als oder größer oder gleich arg2
.
Hatten Sie Ihren Ausdruck also geschrieben als
a=start; n=100; [[ " stop start status " =~ " $a " && $n -lt 3 ]] && echo ok || echo bad
bad
es hätte wie erwartet funktioniert.
Oder selbst wenn Sie die Verwendung arithmetischer Ausdrücke erzwungen hätten, indem Sie $
vorangestellt hätten vor ((..))
und schrieb es wie folgt (beachten Sie, dass bash kein dokumentiertes Verhalten für $((..))
hat innerhalb von [[..]]
). Das wahrscheinlich erwartete Verhalten ist, dass der arithmetische Ausdruck vor dem [[..]]
erweitert wird ausgewertet und die resultierende Ausgabe wird in einem String-Kontext als [[ 0 ]]
ausgewertet was eine nicht leere Zeichenfolge bedeutet.
a=start; n=5; [[ " stop start status " =~ " $a " && $(( $n < 3 )) ]] && echo ok || echo bad
Das Ergebnis würde trotzdem schlecht aussehen, weil der arithmetische Ausdruck innerhalb von [[..]]
zerlegt in einen unären String, nicht leeren Vergleichsausdruck als
$(( 5 < 3 ))
0
[[ -n 0 ]]
Das Ergebnis der arithmetischen Auswertung 0
(false) wird vom Testoperator als Nicht-Null-Entität angenommen und auf der rechten Seite von &&
als wahr bestätigt . Dasselbe würde auch für den anderen Fall gelten, z. sagen Sie n=1
$(( 1 < 3 ))
1
[[ -n 1 ]]
Um es kurz zu machen, verwenden Sie die richtigen Operanden für arithmetische Operationen innerhalb von [[..]]
.
((
ist ein "Schlüsselwort", das die arithmetische Anweisung einleitet. Innerhalb von [[
, Sie können jedoch keine anderen Anweisungen verwenden. Sie können Verwenden Sie jedoch Klammern, um Ausdrücke zu gruppieren, also (( ... ))
ist:eine redundante "Doppelgruppe". Die folgenden sind aufgrund der Vorrangigkeit von <
alle äquivalent und &&
:
[[ " stop start status " =~ " $2 " && (($#<3)) ]]
[[ " stop start status " =~ " $2 " && ($#<3) ]]
[[ " stop start status " =~ " $2 " && $#<3 ]]
Wenn Sie einen ganzzahligen Vergleich wünschen, verwenden Sie -lt
statt <
, aber Sie müssen auch nicht alles in [[ ... ]]
einfügen . Sie können eine bedingte Anweisung und eine arithmetische Anweisung zusammen in einer Befehlsliste verwenden.
{ [[ " stop start status " =~ " $2 " ]] && (($#<3)) ; } || { echo "Usage $0 file_name command"; exit 1;}
In diesem Fall ... && ... || ...
wird so funktionieren, wie Sie es erwarten, obwohl dies im Allgemeinen nicht der Fall ist. Bevorzugen Sie einen if
Anweisung statt.
if [[ " stop start status " =~ " $2 " ]] && (($#<3)); then
echo "Usage $0 file_name command"
exit 1
fi