Hola HumanOS! Continuamos con el estudio de Bash, el Bourne Again Shell de GNU. En este artículo nos referiremos al Control de flujo.

Bash9

Control de flujo:

Las sentencias de control de flujo son un denominador común de la mayoría de los lenguajes de programación, incluido Bash.
En este artículo veremos las sentencias de control de flujo ( ifelsefor, whileuntilcaseselect ).

Las sentencias if, elif y else:

La sentencia condicional tiene el siguiente formato:

$ if condicion
$ then
sentencias…
$ elif condicion
$ then
sentencias…
$ else
sentencias…
$ fi

Este lenguaje nos obliga a que las sentencias estén organizadas con estos retornos de carro, aunque algunas personas prefieren poner los then en la misma línea que los if, para lo cual debemos de usar el separador de comandos, que en Bash es el punto y coma (;) así:

$ if condicion ; then
Sentencias…
$ elif condicion ; then
sentencias…
$ else
sentencias…
$ fi

Aunque no es obligatorio que sea así, normalmente un código de terminación 0 significa que el comando terminó correctamente, y un código entre 1 y 255 corresponde a posibles códigos de error, esto puede ser muy útil a la hora de comprobar y controlar que los programas terminen correctamente y para saber el tipo de error ocurrido…

Las sentencias return y exit:

Los comandos UNIX retornan un código de terminación indicando el resultado de una operación, pero qué pasa si estamos haciendo una función: ¿Cómo retornamos el código de terminación?
Para ello podemos usar la variable especial ‘?’, cuyo valor es ‘$?’, y que indica el código de terminación del último comando ejecutado por el shell. Por ejemplo:

$ cd direrroneo
-bash: cd: direrroneo: No such file or directory
$ echo $?
1

Al haber fallado el último comando $? vale 1. Sin embargo, si el comando se ejecuta bien $? valdrá 0:

$ cd direxistente
$ echo $?
0

La variable ? debe de ser leída justo después de ejecutar el comando, luego es muy típico guardar su valor en una variable ct=$? para su posterior uso.
El otro elemento que necesitamos para devolver el código de terminación de una función es la sentencia return [ct], la cual hace que abandonemos la función devolviendo el código de terminación que pasemos en ct. El parámetro ct es opcional y se puede omitir, en cuyo caso se devuelve el valor de la variable ? en el momento de ejecutarse return, es decir, el código de terminación del último comando ejecutado. Si la función termina sin la sentencia return (como ha pasado hasta ahora), la función también devuelve el código de terminación de la última sentencia ejecutada.
return puede ser usada sólo dentro de funciones y scripts ejecutados con source. Por contra, la sentencia exit [ct] puede ser ejecutada en cualquier sitio, y lo que hace es abandonar el script (aunque se ejecute dentro de una función). La sentencia exit suele usarse para detectar situaciones erróneas que hacen que el programa deba detenerse, aunque a veces se utiliza para “cerrar” un programa.

El bucle for:

El bucle for en Bash es un poco distinto a los bucles for tradicionales de otros lenguajes como C o Java, y se parece más al bucle for each de otros lenguajes, ya que aquí no se repite un número fijo de veces, sino que se procesan las palabras de una frase una a una.
Su sintaxis es la siguiente:

for var [in lista]
do
·····
Sentencias que usan $var
·····
done

Un breve ejemplo:

$ for planeta in Mercury Venus Terra Marte Jupiter Saturno
$ do
$ echo $planeta # Imprime cada planeta en una línea
$ done

Los bucles while y until:

Su sintaxis es:

while comando
do
·····
done
until comando
do
·····
done

 

En este caso el comando también puede ser una condición encerrada entre []. La única diferencia entre while y until es que while se ejecuta mientras que el código de terminación del comando sea exitoso, es decir 0, mientras que until se ejecuta hasta que el código de terminación sea exitoso, según esto until se puede interpretar como ejecutar varias veces un comando hasta que tenga éxito.
El siguiente ejemplo es un script que muestra los directorios de PATH, usando un bucle while y aprovechando el hecho de que una cadena en un test de condición evalúa por verdadero cuando no está vacía, y por falso cuando está vacía:

# Script que muestra los directorios de PATH
path=$PATH
while [ $path ]; do
echo ${path%%:*}
if [ ${path#*:} = $path ]; then
path=
else
path=${path#*:}
fi
done

(nota: el trabajo con expresiones regulares se profundizará en artículos posteriores)

La comprobación [${path#*:} = $path ] se hace para que cuando quede un sólo directorio sin dos puntos pongamos la variable path a vacía, ya que el patrón del operador de búsqueda de patrones no se cumple si la cadena no tiene el símbolo dos puntos (:).

La sentencia case:

Mientras que esta sentencia en lenguajes como C o Java se usa para comprobar el valor de una variable simple, como un entero o un carácter, en Bash esta sentencia permite realizar una comparación de patrones con la cadena a examinar.
Su sintaxis es la siguiente:

case cadena in
patron1)
Sentencias ;;
patron2)
Sentencias ;;
·····
esac

Cada patrón puede estar formado por varios patrones separados por el carácter pipe (|). Si la cadena cumple alguno de los patrones, se ejecutan sus correspondientes sentencias (las cuales se separan por ;) hasta ;;.

La sentencia select:

select variable [in lista]
do
Sentencias que usan $variable
done

Vemos que tiene la misma sintaxis que el bucle for, excepto por la palabra reservada select en vez de for.
La sentencia genera un menú con los elementos de la lista, donde asigna un número a cada elemento, y pide al usuario que introduzca un número. El valor elegido se almacena en variable, y el número elegido en la variable REPLY. Una vez elegida una opción por parte del usuario, se ejecuta el cuerpo de la sentencia y el proceso se repite en un bucle infinito.
Aunque el bucle select es infinito (lo cual nos permite volver a pedir una opción cuantas veces haga falta), el bucle se puede abandonar usando la sentencia break. La sentencia break, al igual que en C y Java, se usa para abandonar un bucle, y se puede usar en el caso, tanto de select, como de los bucles for, while y until. Pero a diferencia de C y Java no sirve para abandonar la sentencia case, sino que ésta se abandona usando los dos punto y coma (;;).

Y hasta aquí este artículo, en el próximo profundizaremos un poco más…
Hasta entonces.
Fuentes:

*Programación en BASH – COMO de introducción (por Mike G, julio del 2000) disponible en dynamo.com.ar
*El shell Bash (por Fernando López Hernández, Septiembre 2005) disponible en macprogramadores.org