GNU/Linux >> Linux Esercitazione >  >> Linux

Perché Bash `(())` non funziona all'interno di `[[]]`?

La pagina man di GNU bash per [[..]] spiega che l'operatore esegue un'espressione condizionale e

Restituisce uno stato di 0 o 1 a seconda della valutazione dell'espressione condizionale expression . 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 se arg1 è uguale a, diverso da, minore di, minore o uguale a, maggiore di, o maggiore o uguale a arg2 , 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

Linux
  1. Perché il ~/.bash_profile non funziona?

  2. Perché la sostituzione del processo Bash non funziona con alcuni comandi?

  3. Perché Lsdel in Debugfs non funziona?

  4. Perché non posso usare Cd in uno script Bash??

  5. Perché `esce &` non funziona?

CentOS 8 VM non funziona in VirtualBox 5.2 su Ubuntu 18.04

Perché "\d" non funziona nelle espressioni regolari in sed?

Perché il mio collegamento simbolico non funziona?

perché un ciclo while bash non esce durante il piping al sottocomando terminato?

perché eliminare la cronologia di bash non è sufficiente?

perché a gdb non piacciono gli alias