Usando expr, $ (()), (())

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

Respuesta

  1. Para aritmética, expr es arcaico. No lo use. *

  2. $((...)) 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 en echo declaraciones:

    $ 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 
  3. Si desea flotar cálculos de puntos, utilice bc o awk:

    $ 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 s es 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 : REGEX se pueden escribir como case STRING in PATTERN). expr solo 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 : REGEX pueden escribirse como case STRING in PATTERN). expr solo 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.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *