Apuntes mientras aprendo sobre software y computadoras.

Computación

Programar en bash: definición de loop

Entonces, continuamos con nuestra noble tarea de aprender a programar en Bash, esta vez agregando una definición del concepto de loop.

Vamos a concentrarnos, abrir esa terminal de Linux y… si, a ver otro tema dentro de este aparentemente infinito mundo de la informática.

Primero, donde estamos. La vez anterior “cerramos” (entre comillas) el tema de evaluar condicionales y los conectores lógicos.

Tal vez no conocemos todo del tema, pero conocemos bastante como para defendernos al momento de crear un script. Bastante bien.

Segundo, vamos a plantarnos en el tema de hoy. Lo que hoy me interesa hacer es crear un apunte sobre los loops, ese tema que se repite, y se repite, y se repite hasta que se termina.

O que sigue sin detenerse hasta que la memoria aguanta o nos da error. Pero imaginemos por un momento que ahora si, el loop gira hasta un posible infinito.

Antes de continuar, lo mejor seria tratar de definir qué es un loop.

¿Qué es un loop?

Es el momento de dar una definición de loop. O como bien se imaginan, es momento de inventar nuestra propia definición de loop.

Quiero decir, buscándolo en el diccionario vemos que loop se refiere a: vuelta, bucle, circulo y repetición.

No vamos a tener que inventar mucho.

Algunos ejemplos en la vida diaria de loop:

– Dar tres vueltas completas al rededor de la manzana.

– Escuchar 25 veces seguidas la misma canción puesta en “repetir”.

– Ver una decena de veces la misma escena de una película que nos gusto mucho (o muy poco).

En teoría el loop puede no tener un límite y puede continuar sin detenerse infinitas veces. Como por ejemplo, mirar tu imagen situada entre dos espejos. Tu reflejo se ve dentro del espejo, y dentro del espejo que se refleja, y dentro del espejo, una y otra vez.

Como una de esas pinturas de M.C.Escher por ejemplo.

Así que ya tenemos la base de lo que es un loop. Ahora necesitamos llevarlo a la creación de programas.

Loops en la shell

En este exacto momento no nos interesa un posible loop infinito.

Si nuestro script se queda en ese tipo de loop, el programa va a funcionar sin detenerse hasta que lo cerremos o hasta que resulte en un error que lo detenga.

Nos interesa usar el tema para hacernos las cosas más fáciles.

Detengamos aquí nuestra definición teórica de loop para verlo ahora aplicado al momento de programar dentro de Bash.

Y básicamente hay dos formas de usarlos:

El comando for:

Esta forma es sencilla. Pero para que engañarnos, todo parece sencillo al principio. En este caso generamos el loop revisando una lista que le damos al programa.

En castellano for puede leerse como la palabra “por” o también como “para”.

Digamos como un ejemplo que tenemos la siguiente linea de código:

for i in 1 2 3; do

Lo que quiere decir es: “para i en 1 2 3; hacer”.

La i de la oración se refiere a los integers, los números enteros. Pero podría ser otra cosa, como strings para texto. Lo importante es que las vueltas se dan al rededor de una lista, que nosotros asignamos o definimos.

Por ejemplo, podría ser:

for str in a b c; do

Y vemos que también agregamos algo nuevo, la palabra do qué significa “hacer”. Palabras como for, in (en) y doforman parte del vocabulario de la shell.

Breve interrupción:

Otra cosa rápida, podemos utilizar el punto y coma (;) como una forma de separación igual a comenzar una linea nueva.

Por ejemplo, es lo mismo decir

if [ a = a]; then
echo terminó el ejemplo
fi

Qué decir:

if [ a = a]
then
echo terminó el ejemplo
fi

Personalmente me gusta más la segunda opción, porque me resulta más sencilla de leer. Pero vos utilizá la que mejor te parezca.

Mejor volvamos con nuestro tema de programar en bash, avanzando con la definición de loop con…

Más loops utilizando «for»

Vamos a probar con un script rápido para ver como funciona este tipo de loops.

Huy, casi me olvido, en el loop la sintaxis se cierra con la palabra done que significa “terminado” o “está terminado”. Es en algo similar a lo que hacíamos con el condicional if, solo que en ese caso cerrábamos el bloque usando fi en lugar de done.

Todos los comandos que van a ejecutarse están entre do y done.

#!/bin/bash
for i in 1 2 3
do
echo $i
done

Ese es el ejemplo básico entre los básicos.

En un primer momento, le decimos al programa que la variable i (integer) esta limitado entre los valores 1, 2, y 3 de la lista.

Entonces el loop va a girar tres veces antes de terminarse, ejecutando el comando echo $i para cada valor de i.

Lo que hace echo $i es imprimir el valor de la variable i en esa vuelta determinada. Realmente el comando podría ser cualquier otro, crear un directorio, mover un archivo o cualquier otra cosa más original que escapa a mi mente ahora mismo.

Con esto tenemos una buena base de los loops con la palabra clave for. Vamos a ver el otro tipo de loop que tenemos a nuestra disposición.

Loops utilizando while

Este loop es ligeramente, ligeramente más complejo que el anterior. Digamos primero que while puede traducirse por “mientras tanto”.

Este caso es algo más complejo, porque while continua ejecutando los comandos que le damos (los que aparecen entre do y done)mientras sus argumentos devuelvan cero (mientras resulten verdaderos o no terminen en error).

El loop solamente va a detenerse cuando los argumentos regresen “no cero” (sean falsos, dicho de mi forma simplificada) o cuando nosotros le demos la orden de terminar.

Vamos a probar con un ejemplo. Pero cuidado, es potencialmente infinito y para terminarlo vas a necesitar presionar ctrl+z (o bueno, cerrar la terminal que tenés abierta).

#!/bin/bash

while [ a = a ]
do
echo esto es potencialmente infinito
done

Cuando pongas a correr este programa no se va a detener nunca.

Lo que sucede es que while revisa si la comparación a = a devuelve cero. Como es verdadera, pasa a ejecutar el comando echo.

Pero como nada interrumpe este loop, se convierte en un bucle que no se detiene por si solo, donde [ a = a ] siempre es verdadero en cada vuelta.

Me cuesta pensar ahora mismo otros ejemplos de loop utilizando while (o al menos algún ejemplo que no implique leer archivos externos).

Hay sin embargo algunos posibles cortes que podemos darle al loop, por medio de:

Tres declaraciones: until, break y continue

Until

La primera de nuestras palabras clave es until, y significa “hasta qué”. Lo que conseguimos es que el loop se rompa en cuanto el argumento que la acompaña resulte verdadero. De alguna manera es como el anti while:

until [ a = a ]
do
echo esto es potencialmente infinito
done

Como la comparación [ a = a ] resulta verdadera, inmediatamente regresa cero y el programa se corta.

Break

Esta palabra break, que podemos traducir en este caso como “frenar” o “romper”, hace justamente lo que promete. Causa que el programa frene el loop inmediatamente cuando se topa con ella.

Una vez más, lucho con crear ejemplos que aclaren todo un poco más. Empecemos por lo más fácil, cortar el anterior loop infinito usando break:

while [ a = a ]
do
echo esto es potencialmente infinito
break
done

Eso detiene el loop, pero admito que no es muy útil. Al menos demuestra como funciona el quiebre del loop, así que podemos decir que entendimos eso.

Continue

Dejo para el final la declaración continue (continuar) y se utiliza muchas veces en conjunto con break.

Lo que se consigue al usarlo es que el loop pase directamente a la rama interna que sigue. Todo esto mantiene los comandos aun entre do y done.

No profundizo mucho en ella, porque un no tuve la ocasión de usarla en un ejemplo que realmente pudiera desarrollar su utilidad.

Pero en cuanto tenga un ejemplo, voy a actualizar el punto.

Conclusión:

Aunque es posible entender la definición de loop, es difícil encontrarle el lugar correcto dentro del panorama general de programar en bash.

En especial siendo que estamos empezando con todo esto, y nos estamos sobrecargando de información.

Seguro esto va a modificarse cuando necesitamos crear programas más complejos, en ese momento la idea de loop va a demostrar ser útil.

Algo importante de destacar es que la misma idea de loop aparece en otros lenguajes de programación, como por ejemplo Python. El trabajo que estamos haciendo ahora va a rendir nuevos frutos cuando estudiemos otros lenguajes.

Como siempre, me gustaría leer tu opinión en los comentarios.

La seguimos en el próximo apunte.

Dejar una respuesta