Categorías
GNU-Linux Script

Crea y ejecuta tu primer script de Bash Shell

Bucles

Bucles en Bash

La capacidad de hacer bucles es una característica muy poderosa de los scripts de bash. Los bucles tienen una gran variedad de usos.

En este capítulo exploraremos las tres diferentes estructuras de bucles de bash. También aprenderas a utilizar los bucles para recorrer elementos de matrices.

Además, aprenderas a usar las sentencias break y continue para controlar los bucles, y finalmente, aprenderas a crear bucles infinitos.

Bucles For en Bash

Los bucles for son uno de los tres tipos diferentes de estructuras de bucle que puedes utilizar en bash. Hay dos estilos diferentes para escribir un bucle for.

  • Bucles for al estilo C
  • Usar el bucle for en una lista/rango de elementos

Bucles for al estilo C en Bash

Si estás familiarizado con un lenguaje de programación tipo C o C++, entonces reconocerás la siguiente sintaxis del bucle for:

for ((inicializador ; condición ; incremento)); do
[COMANDOS]
done

Utilizando la sintaxis al estilo de C mencionada anteriormente, el siguiente bucle for imprimirá «Hola Amiga» diez veces:

for ((i = 0 ; i < 10 ; i++)); do
	echo "Hola Amiga"
done

El bucle for primero inicializa la variable entera i a cero y luego comprueba la condición (i <10); si es verdadera, entonces el bucle ejecuta la línea echo «Hola Amiga» e incrementa la variable i en 1, y luego el bucle se ejecuta una y otra vez hasta que i ya no es menor que 10.

$ bash hola.sh 
Hola Amiga
Hola Amiga
Hola Amiga
Hola Amiga
Hola Amiga
Hola Amiga
Hola Amiga
Hola Amiga
Hola Amiga
Hola Amiga

Bucles for lista/rango en Bash

También existe otra variación de la sintaxis del bucle for que resulta especialmente útil si se trabaja con una lista de archivos (o cadenas), un rango de números, matrices, la salida de un comando, etc. La sintaxis del bucle for de lista/rango tiene la siguiente forma::

for item in [LISTA]; do
[COMANDOS]
done

Por ejemplo, el siguiente bucle for hace exactamente lo mismo que el bucle for al estilo C que habías creado en la sección anterior:

for i in {1..10}; do
	echo "Hola Amiga"
done

El script var.sh de abajo mostrará todos los archivos y directorios que existen bajo el directorio /var:

#!/bin/bash

for i in /var/*; do
	echo $i 
done

A continuación se muestra un ejemplo de salida cuando se ejecuta el script var.sh:

$ ./var.sh
/var/backups
/var/cache
/var/crash
/var/lib
/var/local
/var/lock
/var/log
/var/mail
/var/metrics
/var/opt
/var/run
/var/snap
/var/spool
/var/tmp

Bucles While en Bash

El bucle while es otro bucle popular e intuitivo que puedes utilizar en los scripts de bash. La sintaxis general de un bucle while es la siguiente:

while [ condicion ]; do
[COMANDOS]
done

Por ejemplo, el siguiente script 3×10.sh utiliza un bucle while que imprimirá los diez primeros múltiplos del número tres:

#!/bin/bash

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

Esta es la salida del script anterior::

$ ./3x10.sh
3
6
9
12
15
18
21
24
27
30

Primero inicializa la variable num a 1; luego, el bucle while se ejecutará mientras num sea menor o igual a 10. Dentro del cuerpo del bucle while, el comando echo imprime el valor de num multiplicado por tres y luego incrementa num en 1.

Bucles Until en Bash

Si vienes de un entorno C/C++, puede que estés buscando un bucle do-while, pero ese no existe en bash.

Hay otro tipo de bucle que existe en bash. El bucle until sigue la misma sintaxis que el bucle while:

until [ condición ]; do
[COMANDOS]
Done

La diferencia clave entre el bucle until y el bucle while está en la condición de prueba. Un bucle while seguirá ejecutándose mientras la condición de prueba sea verdadera; por el contrario, un bucle until seguirá ejecutándose mientras la condición de prueba sea falsa.

Por ejemplo, puede crear fácilmente el script 3×10.sh con un bucle until en lugar de un bucle while; el truco aquí es negar la condición de prueba:

#!/bin/bash

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

Observa que la negación de la condición de prueba [ $num -le 10 ]; es [ $num -gt 10 ];

Más información sobre los bucles en los scripts bash

Ahora que estás familiarizado con los bucles en los scripts de bash

A estas alturas deberías estar familiarizado con los arrays en bash.

Los bucles For son a menudo la opción más popular cuando se trata de iterar sobre los elementos de un array.

Por ejemplo, el siguiente script primos.sh itera e imprime cada elemento del array primos:

#!/bin/bash

primos=(2 3 5 7 11 13 17 19 23 29)
for i in "${primos[@]}"; do
	echo $i
done 

Esta es la salida del script primos.sh:

$ ./primos.sh
2
3
5
7
11
13
17
19
23
29

Uso de Break y Continue en bucles bash

A veces puedes querer salir de un bucle prematuramente o saltarte una iteración del mismo. Para ello, se pueden utilizar las sentencias break y continue.

La sentencia break finaliza la ejecución de un bucle y pasa el control del programa al siguiente comando o instrucción que sigue al bucle.

Por ejemplo, el siguiente bucle sólo imprimiría los números del uno al tres:

for ((i=1;i<=10;i++)); do
	echo $i
	if [ $i -eq 3 ]; then
		break
	fi
done

También se puede utilizar una sentencia continue para saltar una iteración del bucle. El bucle continúa y pasa a la siguiente iteración pero los comandos después de las sentencias continue se saltan en esa iteración parcial.

Por ejemplo, el siguiente script impares.sh sólo imprimiría los números impares del uno al diez ya que se salta todos los números pares:

#!/bin/bash
for ((i=0;i<=10;i++)); do
	if [ $(($i % 2)) -ne 1 ]; then
		continue
	fi
	echo $i
done

Esta es la salida que imprime los números impares:

$ ./impares.sh
1
3
5
7
9

Bucles infinitos en bash

Un bucle infinito es un bucle que se ejecuta eternamente; esto ocurre cuando la condición de prueba del bucle es siempre verdadera.

En la mayoría de los casos, los bucles infinitos son producto de un error lógico humano.

Por ejemplo, alguien que quiera crear un bucle que imprima los números del 1 al 10 en orden descendente puede acabar creando el siguiente bucle infinito por error:

for ((i=10;i>0;i++)); do
	echo $i
done 

El problema es que el bucle sigue incrementando la variable i en 1. Para solucionarlo, hay que cambiar i++ por i–:

for ((i=10;i>0;i--)); do
	echo $i
done 

En algunos casos, es posible que quieras crear intencionadamente bucles infinitos para esperar a que se cumpla una condición externa en el sistema. Puedes crear fácilmente un bucle for infinito de la siguiente manera:

for ((;;)); do
	[COMANDOS]
done 

Si en cambio quieres crear un bucle while infinito, entonces puedes hacerlo de la siguiente manera:

while [ true ]; do
	[COMANDOS]
done