ESTRUCTURAS ITERATIVAS (BUCLES)

Antes de comenzar con este tema, debemos tener en cuenta algo muy importante:

NOTA: Las estructuras iterativas pueden generar bucles infinitos, por lo que deben escribirse con mucho cuidado.

Bucle for y for-in

En Bash, también la sintaxis del bucle for es muy similar a la de muchos lenguajes de programación:

for (( inicio; condición; incremento )); do
    # código
done

O bien:

for (( inicio; condición; incremento ))
do
    # código
done

Por ejemplo, mostrar los números del 1 al 10:

for (( i=1; i<=10; i++ )); do
    echo $i
done

Una variante de este bucle es el de for-in con el que se pueden recorrer directorios, rangos, arrays, etcétera:

for elemento in rango; do
    # código
done

Recuerda que los rangos de números se escriben como {5..68} y los de letras como {b..y}. Entonces el ejemplo anterior se podría reescribir así:

for i in {1..10}; do
    echo $i
done

En cuanto a los arrays, la expresión para recorrerlo es con {$[array][*]}. He aquí un ejemplo:

arboles=("Araucaria" "Cedro" "Roble" "Eucalipto" "Pino")

for arbol in ${arboles[*]}; do
    echo $arbol
done

Para conocer el contenido de un directorio simplemente se especifica con un asterisco (*) al final de la ruta, para abarcar todos sus archivos y subdirectorios:

for elem in /home/*; do
    echo $elem
done

Bucle while

La estructura del bucle while no es muy diferente a la de otros lenguajes:

valor_inicial
while [[ condición ]]; do
    # código
    # incremento
done

Es muy importante recordar establecer un valor inicial y un incremento para evitar bucles infinitos. El incremento se puede expresar como ((valor_inicial++)).

Siguiendo el ejemplo anterior, con el bucle while sería así:

i=1
while [[ $i -le 10 ]]; do
    echo $i
    ((i++))
done

Bucle until

Muchos lenguajes de programación cuentan con el bucle do-while, pero esto no existe en Bash. En cambio sí cuenta con una estructura llamada until (hasta que) que, al contrario que la de while, ejecuta el código mientras la condición sea falsa, es decir, hasta que la condición se cumpla. En otras palabras, la condición en until es contraria a la que sería en while.

La sintaxis es:

valor_inicial
until [[ condición ]]; do
    # código
    # incremento
done

Aplicándolo al ejemplo que venimos viendo:

i=1
until [[ $i -gt 10 ]]; do
    echo $i
    ((i++))
done

Vemos que la condición pasa de ser menor o igual a 10 (-le 10) a ser directamente mayor que 10 (-gt 10).

break y continue

Nuevamente, al igual que con otros lenguajes, Bash cuenta las palabras reservadas break que nos permite salir del bucle y continue que nos permite omitir una iteración, bajo ciertas condiciones.

NOTA: En la estructura case no se utiliza break al final de cada opción.

Veamos en el siguiente ejemplo una aplicación de break. En este caso se muestran solamente los números del 1 al 7 porque el bucle se interrumpe al llegar a este valor:

i=1
while [[ $i -le 10 ]]; do
    if [[ $i -eq 7 ]]; then
        break
    fi
    echo $i
    ((i++))
done

En cuanto a continue, en el siguiente caso se muestran todos los números menos el 4:

i=0
while [[ $i -le 10 ]]; do
    ((i++))
    if [[ $i -eq 4 ]]; then
        continue
    fi
    echo $i
done

Aquí hay algo muy importante a tener en cuenta: el contador comienza desde 0 en vez de 1 y se incrementa antes del if.

NOTA: En el caso de continue, las líneas que le siguen serán ignoradas porque el programa saltará directamente al inicio del bucle. Por lo tanto, es recomendable que el incremento ocurra antes del condicional para evitar un bucle infinito.

Además es necesario sustituir -le por -lt para que se imprima hasta el número 10 (de lo contrario, se haría una iteración más y se incluiría el 11).

Y por supuesto, también se pueden combinar ambos términos en un mismo código:

i=0
while [[ $i -le 10 ]]; do
    ((i++))
    if [[ $i -eq 4 ]]; then
        continue
    fi
    echo $i
    if [[ $i -eq 7 ]]; then
        break
    fi
done

Al ejecutarlo se muestran únicamente los números del 1 al 7, salvo el 4.

Ejercicios

  1. Usando el bucle for simple, crear un programa que muestre los números enteros comprendidos entre 28 y 51 incluidos.
  2. Usando esta vez el bucle for-in, crear un array con los nombres analía, bernardo, catalina, david, ester, fabricio, gabriela y héctor, y que los muestre con todas las letras en mayúsculas.
  3. Con el bucle while, imprimir todos los números enteros entre 105 y 147 que sean pares (Pista: usar el operador de módulo).
  4. Con el bucle until, mostrar todos los enteros entre 39 y 16 (no incluido) en orden descendente, y que al final imprima la cantidad total de números.
  5. Usar el bucle for-in, el condicional case y continue para imprimir el rango entre la A y la Z, excepto las letras D, J, N y W.
  6. Usar el bucle for-in, el condicional if y break para imprimir todas las letras de la k a la v, interrumpiendo el bucle en la letra t.