Differenza tra let, expr e $ []


23

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, expr è più lento perché non è un vero e proprio shell incorporato. Ma niente di più.

Risposte:


25

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

  • $((...))è chiamato espansione aritmetica , che è tipico del bashe kshconchiglie. Ciò consente di eseguire semplici aritmetiche di numeri interi , senza roba in virgola mobile. Il risultato dell'espressione sostituisce l'espressione, come in echo $((1+1))diventerebbeecho 2
  • ((...))viene definito valutazione aritmetica e può essere utilizzato come parte di if ((...)); theno while ((...)) ; dodichiarazioni. L'espansione dell'aritmetica $((..))sostituisce l'output dell'operazione e può essere utilizzata per assegnare variabili come in i=$((i+1))ma non può essere utilizzata nelle istruzioni condizionali.
  • $[...] è la vecchia sintassi per l'espansione aritmetica che è deprecata. Vedi anche . Questo è stato probabilmente mantenuto in modo che i vecchi bashscript non si rompessero. Non ha funzionato ksh93, quindi la mia ipotesi è che questa sintassi sia specifica per bash. NOTA : gli spazi sono molto importanti qui; non confondere $[1+1]con cose come [ $a -eq $b ]. Il [con spazi è noto come il testcomando e in genere lo si vede nelle parti decisionali. È molto diverso nel comportamento e nello scopo.
  • letè una parola chiave bashe kshche consente la creazione di variabili con una semplice valutazione aritmetica. Se provi ad assegnare una stringa lì come se let a="hello world"avessi un errore di sintassi. Funziona in bashe ksh93.
  • $(...)è la sostituzione dei comandi, in cui 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 ad alcune cose true / false e regex. Questo è un comando shell-neutral.

È anche interessante notare che l'espansione aritmetica e sostituzione di comando sono specificate da standard POSIX , mentre lete $[...]non sono.


1
((...))in realtà può essere utilizzato per gli incarichi in bash, kshe zsh: n=10; ((n+=10)); echo $nstampa 20 e ((x=1)); echo $xstampa 1.
Alexej Magura il

1
@Alexej Grazie. Risposta aggiornata, quella parte rimossa
Sergiy Kolodyazhnyy l'

11
  • letIl comando esegue una valutazione aritmetica ed è una shell integrata.

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

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

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

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

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

  • expr è un comando binario, se si desidera eseguire l'espansione aritmetica all'interno di una sostituzione dei comandi è possibile utilizzarlo:

    echo $(expr 1 + 2) 
    echo `expr 1 + 2`

4

Dal momento che alcune delle risposte sopra menzionano specificamente ksh93vale la pena notare che può fare matematica in virgola mobile, ad esempio:

$ print $((1.0/3)) 
0.333333333333333333

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

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

Almeno un argomento deve essere specificato come un numero a virgola mobile come sopra. Se entrambi sono specificati come numeri interi, viene eseguita solo la matematica dei numeri interi, 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.


Mi viene in mente che potresti essere interessato a inviare una risposta a Posso usare frazioni / decimali in uno script bash? Nonostante il titolo, penso che il contesto chiarisca che altre conchiglie in stile Bourne sono rilevanti, motivo per cui ho pubblicato una zshrisposta . Dato che kshe bashsono più simili tra loro (in generale) di quanto non lo sia nessuno dei due zsh, mi sembra che una kh93risposta basata su tale domanda possa essere abbastanza utile.
Eliah Kagan,

1

letnon funziona in cron. Penso che sia dovuto al letfatto di avere un proprio ambiente. Utilizzare $((...))poiché è POSIX. Per esempio,

let x=1+2
echo x=$x

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

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

genera "x = 3" in tutti i casi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.