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