Tracks
/
Bash
Bash
/
Temario
/
Aritmética
Ar

Aritmética en Bash

{one: "1 ejercicio", many: "%{count} ejercicios", other: "%{count} ejercicios"}

Acerca de Aritmética

Bash puede hacer aritmética, pero solo con números enteros. Si necesitas hacer cálculos de coma flotante, tendrás que recurrir a algún programa externo (como awk o bc).

Los operadores aritméticos aparecen listados (en orden de precedencia) en el manual: Aritmética del shell.

Además, Bash solo realiza operaciones aritméticas en determinados lugares (conocidos como «contextos» aritméticos).

Expansión aritmética

La expansión aritmética se parece a la sustitución de comandos, pero con paréntesis dobles.

$(( expression ))

Esta sintaxis se expande al resultado de evaluar la expresión. Se usa habitualmente para capturar el resultado en una variable:

x=$(( 3 + 4 ))
Note

La cantidad de espacios en blanco dentro de los paréntesis depende de ti. Es una cuestión de estilo y legibilidad.

x=$(( 3 + 4 ))
y=$((5+6))

A tu amable autor le gusta añadir espacios para que la expresión aritmética sea más visible dentro de los paréntesis.

Condicional aritmético

El condicional aritmético se realiza entre paréntesis dobles sin el $ inicial:

(( expression ))

Esto no se expande al resultado. Sin embargo, sí produce un estado de salida.

  • El estado de salida es 0 (éxito) si el resultado de la expresión es distinto de cero.
  • El estado de salida es 1 (fallo) si el resultado de la expresión es cero.
Note

Dentro de ((, Bash usa el mismo sentido de verdadero/falso que el lenguaje C: cero es falso, distinto de cero es verdadero. ¡Esto es lo contrario de cómo Bash evalúa los estados de salida!

Esta sintaxis se usa normalmente en dos lugares:

  1. como la parte de COMANDO de un condicional if o un bucle while.

    if (( x == y - 1 )); then ...
    while (( y > 0 )); do ...
    
  2. como un comando independiente para modificar el valor de una variable.

    (( x = x + 1 ))
    echo "new value for x is $x"
    
    Caution

    Ten cuidado al usar la aritmética de esta forma junto con set -e. Si la expresión se evalúa a cero, el estado de salida será distinto de cero y Bash terminará.

    x=0
    (( x++ ))
    echo "you will see this"
    
    set -e
    x=0
    (( x++ ))
    echo "shell exits on the previous line; you won't see this"
    

    Para un análisis más detallado del operador ++, consulta este artículo sobre postincremento frente a preincremento

Otros lugares con contexto aritmético

Hay algunos otros lugares que son contextos aritméticos:

  • El bucle for aritmético.

    for (( i = 0; i < 10; i++ )); do
        echo "$i"
    done
    
  • La parte del índice de un array indexado numéricamente.

    echo "The next element is ${array[x + 1]}"
    # ................................^^^^^
    

    Para saber más sobre los arrays, lee el documento del concepto Arrays.

  • Las partes de desplazamiento y longitud de la expansión ${var:offset:length}.

  • El comando integrado let.

    • Ten en cuenta que se prefiere (( expression )) a let "expresson". A diferencia de la construcción del condicional aritmético, la expresión let está sujeta a la expansión de nombres de fichero y a la división de palabras, y requiere comillas.
  • La asignación de variables, cuando la variable tiene el «atributo de entero».

    # variable x does not have the integer attribute
    x="3 + 4"
    declare -p x      # => declare -- x="3 + 4"
    
    # variable y has the integer attribute
    declare -i y
    y="4 + 5"
    declare -p y      # => declare -i y="9"
    
    Note

    En opinión del autor, declare -i tiene un uso limitado. Su principal ventaja es que permite aritmética «desnuda» (sin la sintaxis de expresión aritmética). Esto puede causar confusión a quienes leen tu código, ya que las expresiones aritméticas se evalúan en lugares inesperados.

Usar variables en expresiones aritméticas

Aquí tienes un aspecto de los contextos aritméticos que mejora la legibilidad.

height=10
width=20
area=$(( height * width ))

¿Te has dado cuenta de que faltan los signos de dólar $ en las variables de la expresión aritmética? Bash te lo permite. Hace que las expresiones sean mucho más fáciles de leer.

El manual dice:

Dentro de una expresión, también se puede hacer referencia a las variables del shell por su nombre sin usar la sintaxis de expansión de parámetros.

Incluso funciona con los elementos de un array:

point1=(10 15)  # these are (x, y) coordinates
point2=(20 7)
distance_squared=$(( (point1[0] - point2[0])**2 + (point1[1] - point2[1])**2 ))

Pero otras expresiones de parámetros deben usar su sintaxis especial. Por ejemplo, duplicar la longitud de un string:

s="hello world"
len=$(( ${#s} * 2 ))

Y los parámetros posicionales también. Si los dos primeros parámetros posicionales representan la anchura y la altura:

area=$(( $1 * $2 ))
Editar en GitHub El enlace se abre en una nueva ventana o pestaña