GNU/Linux >> Znalost Linux >  >> Linux

Proč Bash `(())` nefunguje uvnitř `[[]]`?

Manuální stránka GNU bash pro [[..]] vysvětluje, že operátor spustí podmíněný výraz a

Vrátí stav 0 nebo 1 v závislosti na vyhodnocení podmíněného výrazu expression . 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 arg2

OP je jeden z -eq , -ne , -lt , -le , -gt nebo -ge . Tyto aritmetické binární operátory vrátí hodnotu true, pokud arg1 je rovno, ne rovno, menší než, menší nebo rovno, větší než nebo větší nebo rovno arg2 , 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

Linux
  1. Proč Lsdel v Debugfs nefunguje?

  2. Proč nefunguje automatické dokončování při zadávání názvu příkazu za „zdroj“?

  3. Proč dokument Parent Shell Here nefunguje pro dílčí příkaz v Dash, ale funguje Bash?

  1. Proč „ukončit &“ nefunguje?

  2. Při instalaci Rust toolchain do Dockeru nefunguje příkaz Bash `source`

  3. chmod nefunguje

  1. Proč můj symbolický odkaz nefunguje?

  2. proč linux bridge nefunguje

  3. Problém(y) s regulárním výrazem v Bash:[^negate] zřejmě nefunguje