Este es uno de los capítulos del tutorial Scripts en Bash. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.
En el capítulo anterior de este tutorial sobre scripts en Bash, viste las posibilidades que habrían los condicionales para dirigir el flujo del funcionamiento del mismo. Como te comenté, en el propio capítulo, esto es el mismo principio en el que se basa la plataforma ifttt. Al final, no se trata de una decisión como las que tomas todos los días a todas horas. Si pasa esto, haz aquello. Así de sencillo. En este capítulo vas a dar un paso en lo que a automatización se refiere. Se trata precisamente de realizar tareas repetitivas o bucles en Bash.
Si Bart Simpson descubriera el poder de Bash para no tener que repetir en cada episodio esas palabras en la pizarra, probablemente se pasaría a Linux de inmediato. ¿Que?¿Como?
Allá vamos. Adéntrate conmigo en el maravilloso mundo de los bucles, pero de la mano de Bash.
Bucles en Bash
Si tienes pocos conocimientos (o ninguno) de programación, con toda seguridad te estás preguntando que es esto de los bucles. Tal y como te decía en la introducción, si tuvieras que hacer como Bart Simpson
, la operativa en Bash sería la siguiente,
echo 'El baño de los chicos no es un parque acuático'
echo 'El baño de los chicos no es un parque acuático'
echo 'El baño de los chicos no es un parque acuático'
...
echo 'El baño de los chicos no es un parque acuático'
No pongo mas porque esto no tiene sentido, ni quiero que me posicione el SEO, pero, imagina que lo tuvieras que repetir mil veces… Menudo tedio, y absurdo. La solución es el uso de alguno de los mecanismos que Bash pone a tu disposición
Bucles en Bash: while
La primera de las estructuras que te permite realizar bucles es While
. Siguiendo con el ejemplo de Bart, esto se pondría de la siguiente forma,
i=0
while [ $i -lt 1000 ]
do
echo 'Cemento Fresco, no hay letrero más bello… bueno, sólo Alto Voltaje.'
((i++))
done
Aquí tienes que fijarte en la forma de incrementar el contador i
, que has utilizado ((i++))
. Recuerda que en el capítulo sobre variables en Bash te comenté que las operaciones matemáticas se encerraban entre dobles paréntesis.
Otra observación interesante es que tienes que inicializar la variable i
, si utilizas corchete simple. Si utilizas corchetes dobles, no necesitas inicializar la variable. Sin embargo, ya te comenté anteriormente la ventaja de utilizar corchete simple por cuestiones de compatibilidad.
Si quieres que aparezca el número de la repetición dentro de la línea, tan solo tienes que cambiar el echo
anterior por lo siguiente,
echo "$i.- Yo no fui, nadie me vio, nadie puede probarlo."
Por otro lado, si quisieras repetir de forma ininterrumpida un bucle, lo puedes hacer utilizando una estructura como,
while true; do
echo "$i.- Vive deprisa, muere joven y deja un cadáver obeso"
((i++))
done
Fíjate aquí que he puesto el do
en la misma línea que el while
, eso si con un ;
de por medio. Se trata de una forma de simplicar la estructura.
Bucles en Bash: until
El siguiente tipo de bucle, es muy parecido al anterior. La diferencia entre ambos, estriba, en que con while
el bucle continuará mientras se cumpla la condición. Sin embargo, en el caso de until
el bucle continuarás hasta que se cumpla la condción.
Así para realizar una cuenta regresiva, para el lanzamiento de un transbordador interestelar, puedes utilizar el siguiente script,
i=10
until [ $i -lt 0 ]
do
echo $i
((i--))
done
Este mismo ejemplo implementado utilizando while
quedaría como puedes ver a continuación,
i=10
while [ $i -gt -1 ]
do
echo $i
((i--))
done
Si, de una forma u otra, podemos resolver un while
con un until
o viceversa.
Bucles en Bash: for
El funcionamiento del bucle for difiere sensiblemente de los que has visto hasta el momento. Aunque también puedes simular los anteriores bucles, como has visto con until
y while
.
Así, para repetir el ejemplo de Bart Simpson, lo podrías hacer como sigue a continuación,
for i in {1..1000}
do
echo "$i.- Yo soy el niño pepino y me siento fresco como una lechuga"
done
Otra opción para realizar el mismo bucle es utilizando una sintaxis similar a la que se utiliza en c
. Así,
for ((i=1;i<=1000;i++))
do
echo "$i.- Si yo hice algo malo y nadie me atrapó, ¿eso me hace bueno?"
done
También puedes iterar sobre cualquier otro tipo de rango. Por ejemplo, si quieres iterar sobre los archivos del directorio,
cont=0
for i in *
do
((cont++))
echo "El archivo numero $cont es $i"
done
Otro interesante ejemplo,
for color in rojo amarillo verde
do
echo "Este es el color $color"
done
Si quisieras imprimir los números impares hasta el número que le pases como primer argumento,
for ((i=1;i<$1;i++))
do
if ((i%2))
then
echo $i
fi
done
Por supuesto que no solo lo puedes utilizar con números y rangos, también lo puedes utilizar con el resultado de una ejecución de un comando. Por ejemplo,
for i in $(ls)
do
echo $i
done
También, puedes expresar todo el bucle Bash en una única línea, utilizando para ello el punto y coma, ;
como separador. Por ejemplo,
for i in $(ls);do echo $i;done
Si quieres ver un interesante uso de for
, te recomiendo le des un vistazo a este artículo sobre como calcular el número Pi utilizando el método Montecarlo
Rangos
Algo interesante que habrás podido observar en las estructuras for
son los rangos. Un rango, lo puedes expresar con un número de inicio y un número de fin. Sin embargo, Bash, es lo suficientemente inteligente, como para interpretar que si el número de inicio, es mayor que el número de fin, lo que tiene que hacer es una cuenta regresiva. Así,
{1..1000}
contará de 1 a 1000{1000..1}
contará de 1000 a 1
Pero, no solo puedes decir que cuente de uno en uno, también le puedes definir paso. Así
{1..1000..2}
contará de 1 a 1000, pero, de dos en dos.{1000..1..-2}
, lo mismo que en el caso anterior, pero de forma regresiva.
Por supuesto que además de ponerlo en un bucle for, también lo puedes utilizar directamente en un echo
, por ejemplo, echo {1..100..5}
Controlando el flujo con break y continue
Dos opciones realmente muy interesantes que tienes para controlar el flujo del programa son break y continue. Como has podido intuir, el primero te permite interrumpir el flujo y el segundo continuarlo.
Esto te puede ser de gran utilidad por ejemplo para controlar el flujo en el caso de hacer un bucle while infinito.
En el siguiente ejemplo, cuando encuentre el primer valor superior a 5
saldrá del bucle
i=0
while :
do
echo $i
((i++))
if [ $i -gt 5 ]
then
break
fi
done
echo "Finaliza con $i"
Sin embargo, en este ejemplo lo que sucederá cuando lo ejecutes, es que cuando encuentre el valor 2
simplemente saltará a la siguiente iteración.
i=-1
while :
do
((i++))
if [ $i -eq 2 ];then
continue
fi
echo $i
if [ $i -gt 5 ];then
break
fi
done
echo "Finaliza con $i"
Así, pues, mientras que break
rompe el bucle, continue
se salta la iteración.
Conclusiones
En este capítulo del tutorial has podido ver como realizar bucles. Esto es una excelente herramienta para evitar repetir una y otra vez una o varias instrucciones.
Además tienes la posibilidad de utilizar rangos, que te permiten definir una secuencia de números.
Por último, tienes dos elementos, como son break y continue, que te servirán para controlar el flujo de la ejecución bucles en Bash.
Más información,