Tracks
/
Bash
Bash
/
Temario
/
Aritmética
Ar

Aritmética en Bash

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

Acerca de Aritmética

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

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

Además, Bash solo realiza aritmética en ciertos 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 comúnmente 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 amigable autor le gusta agregar 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 dentro de paréntesis dobles sin el $ inicial:

(( expression ))

Esto no se expande al resultado. Sin embargo, 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 opuesto a cómo Bash evalúa los estados de salida!

Esta sintaxis se usa típicamente 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 manera junto con set -e. Si la expresión se evalúa como 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 una discusión más detallada sobre el operador ++, consulta este artículo sobre postincremento vs. preincremento

Otros lugares con contexto aritmético

Hay otros pocos 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 con índices numéricos.

    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 )) sobre let "expresson". A diferencia de la construcción del condicional aritmético, la expresión de let está sujeta a la expansión de nombres de archivo 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

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

Usar variables en expresiones aritméticas

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

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

¿Notaste que los signos de dólar $ no aparecen en las variables de la expresión aritmética? Bash te permite hacer eso. 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 para 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 necesitan 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 el ancho y la altura:

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