La pagina man di GNU bash per [[..]]
spiega che l'operatore esegue un'espressione condizionale e
Restituisce uno stato di
0
o1
a seconda della valutazione dell'espressione condizionaleexpression
. Le espressioni sono composte dai primari descritti di seguito in Bash Conditional Expressions.
Ma l'operatore aritmetico è not parte delle espressioni condizionali supportate (primaries ) all'interno di [[..]]
il che significa che l'espressione è forzata a essere eseguita come confronto di stringhe, ad esempio
(( $n < 3))
non viene eseguito in un contesto aritmetico ma altrettanto semplice confronto lessicografico (stringa) come
[[ 100 < 3 ]]
che risulterà sempre vero, perché i valori ASCII per 1
, 0
, 0
compaiono prima di 3
Ma dentro [[..]]
le operazioni aritmetiche sono supportate se usi -lt
, -gt
arg1 OP arg2
OP è uno di
-eq
,-ne
,-lt
,-le
,-gt
o-ge
. Questi operatori binari aritmetici restituiscono vero searg1
è uguale a, diverso da, minore di, minore o uguale a, maggiore di, o maggiore o uguale aarg2
, rispettivamente.
Quindi avevi scritto la tua espressione come
a=start; n=100; [[ " stop start status " =~ " $a " && $n -lt 3 ]] && echo ok || echo bad
bad
avrebbe funzionato come previsto.
O anche se hai forzato l'uso dell'espressione aritmetica anteponendo $
prima di ((..))
e scritto come segue (nota che bash non ha un comportamento documentato per $((..))
all'interno di [[..]]
). Il probabile comportamento previsto è che l'espressione aritmetica sia espansa prima del [[..]]
viene valutato e l'output risultante viene valutato in un contesto di stringa come [[ 0 ]]
che significa una stringa non vuota.
a=start; n=5; [[ " stop start status " =~ " $a " && $(( $n < 3 )) ]] && echo ok || echo bad
Il risultato sarebbe comunque brutto, perché l'espressione aritmetica all'interno di [[..]]
si decompone in una stringa unaria non espressione di confronto vuota come
$(( 5 < 3 ))
0
[[ -n 0 ]]
Il risultato della valutazione aritmetica 0
(false) viene preso come un'entità diversa da zero dall'operatore di test e afferma true sul lato destro di &&
. Lo stesso varrebbe anche per l'altro caso, ad es. dire n=1
$(( 1 < 3 ))
1
[[ -n 1 ]]
Per farla breve, usa gli operandi giusti per le operazioni aritmetiche all'interno di [[..]]
.
((
è una "parola chiave" che introduce l'istruzione aritmetica. Dentro [[
, tuttavia, non puoi utilizzare altre istruzioni. Puoi usa le parentesi per raggruppare le espressioni, quindi questo è ciò che (( ... ))
è:un ridondante "doppio gruppo". I seguenti sono tutti equivalenti, a causa delle precedenze di <
e &&
:
[[ " stop start status " =~ " $2 " && (($#<3)) ]]
[[ " stop start status " =~ " $2 " && ($#<3) ]]
[[ " stop start status " =~ " $2 " && $#<3 ]]
Se vuoi un confronto tra numeri interi, usa -lt
invece di <
, ma non è nemmeno necessario inserire tutto all'interno di [[ ... ]]
. Puoi usare un'istruzione condizionale e un'istruzione aritmetica insieme in un elenco di comandi.
{ [[ " stop start status " =~ " $2 " ]] && (($#<3)) ; } || { echo "Usage $0 file_name command"; exit 1;}
In questo caso, ... && ... || ...
funzionerà nel modo previsto, anche se in generale non è così. Preferisci un if
istruzione invece.
if [[ " stop start status " =~ " $2 " ]] && (($#<3)); then
echo "Usage $0 file_name command"
exit 1
fi