ESTRUCTURAS DE CONTROL

La shell tiene un conjunto de estructuras de control, que son muy parecidos a otros lenguajes de programación. En las siguientes secciones, las sentencias son las series de comandos para ejecutar cuando, mientras o hasta que se cumpla la condición.

if

La sentencia if es muy sencilla, comprueba el resultado de un comando y después ejecuta condicionalmente un grupo de sentencias (statements):

sentencia_if
if se suele usar para realizar una pregunta y para tomar posteriormente una decisión basándose en la respuesta:

saludo
llamamos a este script saludo y nos dá la siguiente salida:

saludo_2
no olvidemos dar permiso de ejecución a nuestro archivo con el comando chmod +x saludo y ejecutarlo con ./saludo.

Este script usa el comando [ para comprobar los contenidos de la variable pregunta. El resultado lo evalúa el comando if, que después permite que se ejecuten diferentes lineas de código.

nota_if
elif

Desafortunadamente, este script tan sencillo genera muchos problemas. Uno de ellos es que interpreta que toda respuesta que no sea si significa no. Podemos evitarlo utilizando la construcción elif, que le permite añadir una segunda comprobación que se realizará cuando se ejecute la parte else de if.

Comprobar usando elif

Se puede modificar el script anterior para que envíe un mensaje de error si el usuario escribe cualquier otra diferente a si o no. Hágalo reemplazando else por elif y añada después otra condición:

elif
Ahora el resultado obtenido es un poco más profesional:

elif_2
El funcionamiento es muy parecido al del ejemplo anterior, pero ahora el comando elif comprueba la variable de nuevo si la primera condición if no es verdadera. Si ninguna de las comprobaciones concluye con éxito, se muestra un mensaje de error y el script existe con el valor 1, que el usuario puede usar en un programa de llamada para comprobar si el script tuvo éxito.

Un problema con las variables

Si ejecutamos otra vez nuestro script comprobamos que si presionamos la tecla ENTER en vez de responder a la pregunta, obtendremos un mensaje de error:

variables_error
El problema lo vemos en la primera clausula if. Cuando if comprobó la variable pregunta al pulsar ENTER, la trató como una cadena en blanco. Por eso, la clausula if tenía esta apariencia:

error_linea

que no es una condición válida. Para evitarlo, debemos usar las comillas («») alrededor de la variable:

variable_error2
Después, una variable vacía proporcionará la comprobación válida:

error_2
El nuevo script tendría esta apariencia:
saludo_final
Ahora, podemos presionar INTRO para responder a la pregunta.
error_corregido
Bash permite eliminar la nueva línea usando el comando echo -n "Lo siento, no reconozco "$pregunta". Introduce si o no".

for

Este comando hace bucles a través de varios valores, puede ser cualquier conjunto de cadenas. Se puede enumerar en el programa o, más comúnmente, en el resultado de una expansión shell de los nombres de archivo.

La sintaxis es sencilla:

for_in

Uso del bucle for con cadenas fijadas

Los valores suelen ser cadenas, de manera que podemos escribir:

ejemplo_for

Que generará la siguiente salida:

cadena_for_semana

Si recordamos anteriormente si encerramos entre comillas los días de la semana se interpretará como si fuera una cadena única siendo uno de los modos de conseguir almacenar los espacios de una variable:

cadena2_1

Vemos el resultado:

cadena2_2

Cómo funciona

Este ejemplo crea la variable semana y le asigna un valor diferente cada vez alrededor del bucle for. Como la shell considera que todas las variables contienen cadenas por defecto, es tan válido usar una cadena alfanumérica como numérica.

Usar un bucle for con expansión de comodín

Se suele usar el bucle for con una expansión shell de los nombres de archivo. Esto significa usar un comodín para el valor de la cadena y con esto permitimos a la shell que complete todos los valores en el tiempo de ejecución.

comodin

Este script usa la expansión shell, * expandiendo los nombres del directorio actual. Se emplea uno a uno como la variable $file dentro del bucle for.

comodin2

En este ejemplo ponemos de manifiesto el uso de la sintaxis $ (command), que estudiaremos detalladamente más adelante. Básicamente, la lista de parámetros del comando for la proporciona la salida del comando que se encuentra dentro de la secuencia $().

La shell expande c* para proporcionar los nombres de todos los archivos que cumplan este patrón.

while

Como por defecto todos los valores shell se consideran cadenas, el bucle for es adecuado para serpentear a través de una serie de cadenas, pero no resulta útil cuando no se sabe de antemano cuántas veces desea ejecutar el bucle.

Cuando tenga que repetir una secuencia de comandos, y no conozca previamente el número de veces que deberá ejecutarse, puede usar el bucle while, que tiene la siguiente sintaxis:

while

Crearemos como ejemplo un programa bastante sencillo que comprobará una contraseña:

contraseña_programa

Ejecutamos el script y tendremos:

contraseña

Evidentemente no se tratas de un modo muy seguro para solicitar una contraseña, pero nos sirve para mostrar la sentencia while. Las sentencias que se encuentran entre do y done se ejecutan constantemente hasta que la condición deja de ser verdadera. En este caso, está comprobando si el valor de pass es igual a atika. El bucle seguirá hasta que $pass equivalga a atika. Después seguirá ejecutando el script de la sentencia que va justo detrás de done.

until

La sentencia until tiene la siguiente sintaxis:

until

Es muy similar al bucle while, pero con el test de condición invertido. En otras palabras, el bucle continúa hasta que la condición es verdadera, no mientras la condición sea verdadera.

until_script

case

La construcción case es un poco más compleja que las que hemos visto hasta el momento. La sintaxis es:

case

La construcción case permite comparar los contenidos de una variable con los patrones de un modo muy sofisticado y luego le permite la ejecución de diferentes sentencias, dependiendo del patrón comparado. Es mucho más sencillo que la opción alternativa para comparar muchas condiciones, que quería usar múltiples sentencias if, else y elif.

case_nota1

La capacidad de comprobar varios patrones y de ejecutar después varias sentencias relacionadas hace que la construcción case sea un buen método para gestionar los datos de entrada del usuario. El mejor modo para comprobar cómo funciona case es mediante un ejemplo que desarrollaremos en tres secciones, mejorando con cada uno la correspondencia de patrones.

case_nota2

Caso I: datos de entrada del usuario

Podemos escribir una nueva versión del script saludo que hace la comprobación de la entrada del usuario mediante la construcción case que será un poco más selectivo y comprensivo ante los datos inesperados.

case_saludo2_script

Cómo funciona

Al ejecutar la sentencia case, adopta los contenidos de respuesta y los compara uno a uno con todas las cadenas. En cuanto una cadena se corresponda con los datos de entrada, el comando case ejecuta el código que aparece tras ) y finaliza.

El comando case realiza la expansión normal de las cadenas que está usando para realizar la comparación. por eso puede especificar parte de una cadena seguida por el comodín *. si usa un único *, se corresponderán todas las cadenas posibles. Coloque otro asterisco tras las cadenas de correspondencia para que la sentencia case finalice con alguna acción preestablecida si no se corresponde ninguna cadena. Esto es posible porque la sentencia case compara las cadenas una a una. No busca el mejor resultado, sino la primera correspondencia. La condición predeterminada suele ser la condición imposible, por eso el uso de * puede ayudar a localizar y solucionar los errores del scripts.

Caso II: unión de patrones

La construcción case anterior es mucho más elegante que la versión múltiple de la sentencia if, pero al unir los patrones, puede obtener una versión mucho más organizada:

case_saludo3

Cómo funciona

Con este script usamos cadenas múltiples con cada entrada de case, de manera que case comprueba muchas cadenas diferentes para cada posible sentencia. Esto hace que el script sea mucho más breve y que, con la práctica, resulte más fácil leerlo. Este código muestra también cómo se puede usar el comodín *, aunque puede hacer corresponder patrones no deseanos. Por ejemplo, si el usuario introduce nose, dicha entrada se corresponderá con n* y aparecerá Buenas tardes, que no es el comportamiento deseado. Tenga en cuenta que el comodín * no funciona entre comillas.

Caso III: ejecutar sentencias múltiples

Finalmente para poder volver a usar el script, necesitamos un valor de salida diferente cuando se use el patrón predeterminado, porque no se comprendieron los datos de entrada:

case_saludo4

Cómo funciona

Para mostrar otro modo de correspondencia de patrones, este código modifica el modo de correspondencia del caso no. También muestra cómo se debe ejecutar múltiples sentencias para cada patrón de la sentencia case. Debemos colocar las correspondencias más explícitas en primer lugar y las más generales en último lugar. Esto es importante porque case ejecuta la primera correspondencia que encuentra, no la más apropiada. Si pone *) en primer lugar, siempre habrá correspondencia, independientemente de los datos de entrada.

atras

Deja un comentario

Este sitio utiliza Akismet para reducir el spam. Conoce cómo se procesan los datos de tus comentarios.