Manuální stránka GNU bash pro [[..]] vysvětluje, že operátor spustí podmíněný výraz a
Vrátí stav
0nebo1v závislosti na vyhodnocení podmíněného výrazuexpression. Výrazy se skládají z primárních položek popsaných níže v části Bash Conditional Expressions.
Ale aritmetický operátor není část podporovaných podmíněných výrazů (primární ) uvnitř [[..]] což znamená, že výraz je nucen běžet jako porovnání řetězců, tj.
(( $n < 3))
není spuštěn v aritmetickém kontextu ale stejně prosté lexikografické (řetězcové) srovnání jako
[[ 100 < 3 ]]
což bude vždy mít hodnotu true, protože hodnoty ASCII pro 1 , 0 , 0 objeví se před 3
Ale uvnitř [[..]] aritmetické operace jsou podporovány, pokud použijete -lt , -gt
arg1 OP arg2OP je jeden z
-eq,-ne,-lt,-le,-gtnebo-ge. Tyto aritmetické binární operátory vrátí hodnotu true, pokudarg1je rovno, ne rovno, menší než, menší nebo rovno, větší než nebo větší nebo rovnoarg2, respektive.
Napsali byste tedy svůj výraz jako
a=start; n=100; [[ " stop start status " =~ " $a " && $n -lt 3 ]] && echo ok || echo bad
bad
fungovalo by to podle očekávání.
Nebo i když jste vynutili použití aritmetického výrazu předponou $ před ((..)) a zapsal to, jak je uvedeno níže (všimněte si, že bash nemá zdokumentované chování pro $((..)) uvnitř [[..]] ). Pravděpodobně očekávané chování je, že aritmetický výraz je rozšířen před [[..]] je vyhodnocen a výsledný výstup je vyhodnocen v kontextu řetězce jako [[ 0 ]] což znamená neprázdný řetězec.
a=start; n=5; [[ " stop start status " =~ " $a " && $(( $n < 3 )) ]] && echo ok || echo bad
Výsledek by stále vypadal špatně, protože aritmetický výraz uvnitř [[..]] se rozloží na unární řetězec, nikoli prázdný porovnávací výraz jako
$(( 5 < 3 ))
0
[[ -n 0 ]]
Výsledek aritmetického vyhodnocení 0 (false) je operátorem testu brán jako nenulová entita a platí true na pravé straně && . Totéž by platilo pro jiný případ také např. řekněte n=1
$(( 1 < 3 ))
1
[[ -n 1 ]]
Stručně řečeno, použijte správné operandy pro aritmetické operace uvnitř [[..]] .
(( je "klíčové slovo", které zavádí aritmetický příkaz. Uvnitř [[ , ale nemůžete použít jiné příkazy. můžete k seskupování výrazů však použijte závorky, takže to je to, co (( ... )) je:nadbytečná "dvojitá skupina". Následující jsou všechny ekvivalentní kvůli prioritám < a && :
[[ " stop start status " =~ " $2 " && (($#<3)) ]][[ " stop start status " =~ " $2 " && ($#<3) ]][[ " stop start status " =~ " $2 " && $#<3 ]]
Pokud chcete srovnání celých čísel, použijte -lt místo < , ale také nemusíte všechno vměstnat do [[ ... ]] . V seznamu příkazů můžete použít podmíněný a aritmetický příkaz společně.
{ [[ " stop start status " =~ " $2 " ]] && (($#<3)) ; } || { echo "Usage $0 file_name command"; exit 1;}
V tomto případě ... && ... || ... bude fungovat tak, jak očekáváte, i když obecně tomu tak není. Preferujte if místo toho prohlášení.
if [[ " stop start status " =~ " $2 " ]] && (($#<3)); then
echo "Usage $0 file_name command"
exit 1
fi