Differenza tra let, expr e $ []

17

Voglio sapere qual è esattamente la differenza tra

a=$[1+1]
a=$((1+1))
let a=1+1
a=$(expr 1 + 1 )

Tutti e 4 assegnano la variabile a con 2, ma qual è la differenza?

Da quello che ho scoperto finora, è che expr è più lento perché non è un built-in della shell reale. Ma non qualcosa di più.

    
posta ADDB 24.07.2017 - 17:35

4 risposte

18

Tutti questi riguardano l'aritmetica, ma in modi diversi e la variabile viene creata con mezzi diversi. Alcuni di questi sono specifici per bash shell, mentre altri no.

  • ((...)) è chiamato espansione aritmetica, che è tipica delle shell bash e ksh . Questo permette di fare semplici aritmetici interi , ma nessuna roba a virgola mobile. ((...)) è solo un'azione, quindi $((..)) sostituisce l'output dell'operazione.
  • $[...] è la vecchia sintassi per l'espansione aritmetica che è deprecata. Vedi anche . Questo è stato probabilmente mantenuto così che i vecchi script bash non si interrompano. Questo non ha funzionato in ksh93 , quindi la mia ipotesi è che questa sintassi sia bash-specifica. NOTA : gli spazi sono molto importanti qui; non confondere $[1+1] con cose come [ $a -eq $b ] . Il [ con spazi è noto come comando test e di solito lo si vede nelle parti decisionali. È molto diverso nel comportamento e nello scopo.
  • let è una parola chiave bash e ksh che consente la creazione di variabili con una semplice valutazione aritmetica. Se provi ad assegnare una stringa come let a="hello world" , otterrai un errore di sintassi. Funziona in bash e ksh93 .
  • $(...) è la sostituzione di comando, dove si prende letteralmente l'output di un comando e si assegna a una variabile. Il tuo comando qui è expr , che accetta argomenti posizionali, come expr arg1 arg2 arg3 , quindi gli spazi sono importanti. È un po 'come un piccolo calcolatore da riga di comando per l'aritmetica dei numeri interi, oltre a qualche tipo di roba vero / falso e regex. Questo è un comando shell-neutral.

Vale anche la pena notare che l'espansione aritmetica e la sostituzione del comando sono specificate dallo standard POSIX , mentre let e $[...] non lo sono.

    
risposta data Sergiy Kolodyazhnyy 24.07.2017 - 18:21
10
  • Il comando

    let esegue la valutazione aritmetica ed è integrato nella shell.

    • Esegui questo comando e non ottieni nulla (valuta solo):

      let 1+2
      
  • $(( )) viene utilizzato per eseguire l'espansione aritmetica : leggi qui

    • Esegui questo e riceverai un errore (a causa dell'espansione):

      $((1+2))
      
  • $[ ] è la vecchia sintassi per l'espansione aritmetica:

      

    Il vecchio formato $ [espressione] è deprecato e verrà rimosso in imminenza di bash.    Pagina di Bash Man

  • expr è un comando binario, se vuoi eseguire l'espansione aritmetica all'interno di un gruppo di comandi puoi usarlo:

    echo $(expr 1 + 2) 
    echo 'expr 1 + 2'
    
risposta data Ravexina 24.07.2017 - 18:27
3

Poiché alcune delle risposte sopra menzionano in modo specifico ksh93 , vale la pena notare che può eseguire calcoli matematici in virgola mobile, ad esempio:

$ print $((1.0/3)) 
0.333333333333333333

Puoi controllare la precisione dell'output con printf, ad esempio:

$ printf "%.4f\n" $((1.0/3))
0.3333

Almeno un argomento deve essere specificato come numero a virgola mobile come sopra. Se entrambi vengono specificati come numeri interi, viene eseguito solo il calcolo matematico intero, ad esempio:

$ print $((1/3))  
0

Questo può essere utile quando hai bisogno di matematica in virgola mobile in uno script di shell poiché puoi evitare di chiamare un comando esterno.

    
risposta data sneezy 29.09.2017 - 00:45
0

let non funziona in cron. Penso che sia dovuto al fatto che let ha il proprio ambiente. Usa $((...)) poiché è POSIX. Ad esempio,

let x=1+2
echo x=$x

in cron, restituisce "x=", ma "x = 3" quando viene eseguito dalla shell.

x=$((1+2))
echo x=$x

restituisce "x = 3" in tutti i casi.

    
risposta data SparkEV 11.01.2018 - 20:06

Leggi altre domande sui tag