La pagina man di GNU bash per [[..]] spiega che l'operatore esegue un'espressione condizionale e
Restituisce uno stato di
0o1a 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 arg2OP è uno di
-eq,-ne,-lt,-le,-gto-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