Diferencia entre let, expr y $ []


23

Quiero saber cuál es exactamente la diferencia entre

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

Los 4 asignan la variable a con 2, pero ¿cuál es la diferencia?

Por lo que descubrí hasta ahora, es que expr es más lento porque no es una construcción real de shell. Pero nada más que eso.

Respuestas:


25

Todos estos tratan con la aritmética, pero de diferentes maneras y la variable se crea por diferentes medios. Algunos de estos son específicos de los bashdepósitos, mientras que otros no.

  • $((...))se llama expansión aritmética , que es típica de las conchas bashy ksh. Esto permite hacer aritmética de enteros simples , sin embargo, no hay cosas de punto flotante. El resultado de la expresión reemplaza a la expresión, ya que en echo $((1+1))se convertiría enecho 2
  • ((...))se conoce como evaluación aritmética y se puede usar como parte de if ((...)); theno while ((...)) ; dodeclaraciones. La expansión de expansión aritmética $((..))sustituye la salida de la operación y se puede usar para asignar variables como en i=$((i+1))pero no se puede usar en declaraciones condicionales.
  • $[...] es la sintaxis anterior para la expansión aritmética que está en desuso. Ver también . Esto probablemente se mantuvo para que los bashscripts antiguos no se rompan. Esto no funcionó ksh93, así que supongo que esta sintaxis es específica de bash. NOTA : los espacios son muy importantes aquí; no confunda $[1+1]con cosas como [ $a -eq $b ]. El [con espacios se conoce como el testcomando, y normalmente lo ves en las partes de toma de decisiones. Es muy diferente en comportamiento y propósito.
  • letes una palabra clave bashy kshque permite la creación de variables con una evaluación aritmética simple. Si intenta asignar una cadena allí let a="hello world", obtendrá un error de sintaxis. Trabaja en bashy ksh93.
  • $(...)es la sustitución de comandos, donde literalmente tomas el resultado de un comando y lo asignas a una variable. Su comando aquí es expr, que toma argumentos posicionales, como expr arg1 arg2 arg3, por lo que los espacios son importantes. Es algo así como una pequeña calculadora de línea de comandos para la aritmética de enteros, más algún tipo de cosas verdadero / falso y expresiones regulares. Este es un comando de shell neutral.

Es también digno de mención que la expansión de la aritmética y la sustitución de comandos se especifican por estándar POSIX , mientras que lety $[...]no lo son.


1
((...))en realidad se puede usar para tareas en bash, kshy zsh: n=10; ((n+=10)); echo $nimprime 20 e ((x=1)); echo $ximprime 1.
Alexej Magura

1
@ Alexej Gracias. Respuesta actualizada, esa parte eliminada
Sergiy Kolodyazhnyy

11
  • letEl comando realiza una evaluación aritmética y es un shell incorporado.

    • Ejecute este comando y no obtendrá nada (solo evalúa):

      let 1+2
  • $(( ))se utiliza para realizar expansión aritmética : lea aquí

    • Ejecute este y obtendrá un error (debido a la expansión):

      $((1+2))
  • $[ ] es la sintaxis anterior para la expansión aritmética:

    El formato anterior $ [expresión] está en desuso y se eliminará próximamente de bash. Bash Man Page

  • expr es un comando binario, si desea hacer una expansión aritmética dentro de una substitución de comando, puede usarlo:

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

4

Dado que algunas de las respuestas anteriores mencionan específicamente ksh93, vale la pena señalar que puede hacer cálculos de coma flotante, por ejemplo:

$ print $((1.0/3)) 
0.333333333333333333

Puede controlar la precisión de la salida con printf, por ejemplo:

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

Al menos un argumento debe especificarse como un número de coma flotante como el anterior. Si ambos se especifican como enteros, entonces solo se realiza la matemática entera, por ejemplo:

$ print $((1/3))  
0

Esto puede ser útil cuando necesita matemática de punto flotante en un script de shell, ya que puede evitar llamar a un comando externo.


Se me ocurre que podría estar interesado en publicar una respuesta a ¿Puedo usar fracciones / decimales en un script bash? A pesar del título, creo que el contexto deja en claro que otros shells de estilo Bourne son relevantes, por eso publiqué una zshrespuesta . Dado que kshy bashson más similares entre sí (en general) que cualquiera de los dos zsh, me parece que una kh93respuesta basada en esa pregunta podría ser bastante útil.
Eliah Kagan

1

letno funciona en cron. Creo que se debe a que lettiene su propio entorno. Úselo $((...))ya que es POSIX. Por ejemplo,

let x=1+2
echo x=$x

en cron, da como resultado "x =", pero "x = 3" cuando se ejecuta desde el shell.

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

da como resultado "x = 3" en todos los casos.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.