En el script de shell podemos sustituir expr $a*$b con $(($a+$b)). 
 Pero por qué no solo con (($a+$b)), porque en cualquier recurso está escrito que (()) es para el cálculo de números enteros. 
 Entonces usamos $(()) cuando hay variables en lugar de valores enteros, ¿verdad? ¿Y qué deberíamos usar en lugar de $(()) cuando las variables pueden recibir valores flotantes? 
Comentarios
- Ver también unix.stackexchange.com/questions/149823/…
 
Respuesta
- 
Para aritmética,
expres arcaico. No lo use. * - 
$((...))y((...))son muy similares. Ambos solo hacen cálculos con números enteros. La diferencia es que$((...))devuelve el resultado del cálculo y((...))no. Por lo tanto,$((...))es útil enechodeclaraciones:$ a=2; b=3; echo $((a*b)) 6((...))es útil cuando desea asignar una variable o establecer un código de salida:$ a=3; b=3; ((a==b)) && echo yes yes - 
Si desea flotar cálculos de puntos, utilice
bcoawk:$ echo "4.7/3.14" | bc -l 1.49681528662420382165 $ awk "BEGIN{print 4.7/3.14}" 1.49682 
 * Por otro lado, expr sigue siendo útil para el manejo de cadenas cuando los globs no son lo suficientemente buenos y se necesita un método POSIX para manejar expresiones regulares. 
Comentarios
- Si expr es arcaico, ¿qué deberíamos usar en lugar del texto expr? '. * '
 -  Si 
ses una variable de shell, su longitud es${#s} - $ {#} significa un número de argumentos y $ (# s} significa un número de caracteres de una variable, ¿verdad?
 - Sí. Eso ' es correcto.
 -  @Stranger Muchos usos de 
expr STRING : REGEXse pueden escribir comocase STRING in PATTERN).exprsolo es útil cuando REGEX no puede ' t expresarse con comodines de shell. 
Answer
expr es antiguo, pero se me ocurre un uso limitado. Digamos que desea buscar una cadena. Si desea permanecer POSIX con grep, debe usar una tubería:
if echo november | grep nov then : do something fi 
expr puede hacer esto sin una tubería:
if expr november : nov then : do something fi 
el único problema es que expr funciona con cadenas ancladas, por lo que si desea hacer coincidir después del principio, debe cambiar el REGEXP:
if expr november : ".*ber" then : do something fi 
 Con respecto a (( )), esta construcción  no es POSIX , por lo que debe evitarse. 
 Con respecto a $(( )), no es necesario que incluya el signo de dólar: 
$ fo=1 $ go=2 $ echo $((fo + go)) 3 
Comentarios
-  Muchos usos de 
expr STRING : REGEXpueden escribirse comocase STRING in PATTERN).exprsolo es útil cuando REGEX no puede ' t expresarse con comodines de shell. 
Respuesta
Parece que los siguientes programas hacen más o menos lo mismo y en realidad no difieren. Pero eso no es cierto.
#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=$((s+1)) echo $s 
Esta es la forma correcta de implementar esto. La expresión s + 1 es evaluada por el shell y puede asignarse a una variable.
#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=`expr $s+1` echo $s 
Aquí la expresión será calculada por el programa expr, que no es un shell incorporado sino un programa externo de Unix. Entonces, en lugar de simplemente agregar 1 ys, se debe iniciar un programa y su salida debe leerse y escribirse en la variable. Iniciar un programa requiere muchos recursos y mucho tiempo. Y este programa se ejecuta 1000000 veces. Entonces el programa será mucho más lento que el anterior. Sin embargo, el código funciona correctamente.
#!/bin/bash -e s=-1000 for (( i=0; i<1000000; i++ )), do ((s=s+1)) echo $s 
Si no se establece la opción -e, el programa también funcionará correctamente. Pero si se establece -e cuando s = -1 y ((s = s + 1)) se calcula. La expresión s = s + 1 se evalúa como 0 y el código de salida de ((0)) es> 0, que es interpretado como un error por el shell y el shell sale del programa.
La razón para establecer el indicador -e es que es la forma más sencilla de procesar errores: deténgase si ocurre un error.