Webmasters, Hacking Ball Z - http://www.hackingballz.com
Estructuras de control, bucles y operadores
http://www.hackingballz.com/articulos/17/1/Estructuras-de-control-bucles-y-operadores/Page1.html
Por Larry Hans Arroyo Vargas
Published on 09.06.08
 

En esta entrega profundizamos en las estructuras de control de BASH, así mismo como los indispensables bucles, sus construcciones y los operadores en general.


La base indiscutible (después de las variables) de todo lenguaje, es la habilidad de tomar decisiones dependiendo de qué circunstancia acontezca en el momento de la ejecución del guion. Para este tipo de casos los lenguajes ofrecen su juego de condicionales y por supuesto las opciones para bucles, que le permiten comportarse de una manera inteligente.

Un ejemplo sencillo sería el siguiente:

#!/bin/bash
VARIABLE=correcto

if [ "$VARIABLE" = "correcto" ]; then
echo "valido"
else
echo "falso"
fi

En este caso, debemos considerar que los espacios entre if [ la variable, el operador, la cadena y el ] final, son importantes, debido a que por defecto no los limita al declararlos, entonces hay que tener cuidado con estos detalles.

El resultado de este ejemplo sería evidentemente el siguiente:

[root@ns01 bash]# sh bash.sh
valido
[root@ns01 bash]#

En el código en la línea 4, utilizamos el operador = que funciona para indicar que si la variable es igual al contenido de la cadena, entonces debe lanzar el resultado positivo.

No obstante IF, THEN y FI, no son las únicas estructuras disponibles, a continuación el detalle de las mismas:

if/else: Ejecuta una serie de comandos dependiendo si una cierta condición se cumple o no.

for: Ejecuta una serie de comandos un número determinado de veces, siempre y cuando se cumplan las condiciones.

while: Ejecuta una seria de comandos mientras que una determinada condición sea cumpla. En general es muy similar a for.

until: Ejecuta una serie de comandos hasta que una determinada condición se cumpla.

case: Ejecuta una o varias listas de comandos dependiendo del valor de una variable.

select: Permite seleccionar al usuario una opción de una lista de opciones en un menú.

La mayoría de condiciones utilizadas con estas construcciones son comparaciones de cadenas alfanuméricas o numéricas, valores de terminación de comandos y comprobaciones de atributos de ficheros. Antes de seguir viendo como estas construcciones operan, vamos a ver como las condiciones se pueden definir y trabajar propiamente hablando.


Operadores de comparación

La comparación de cadenas es vital, a la hora de tomar decisiones dentro de nuestros programas. La intención en muchos casos es verificar la igualdad (o desigualdad), es determinante para continuar con una porción específica de código.

Comparaciones de cadenas alfanuméricas

La comparación de cadenas es vital, a la hora de tomar decisiones dentro de nuestros programas. La intención en muchos casos es verificar la igualdad (o desigualdad), es determinante para continuar con una porción específica de código.

El termino alfanumérico agrupa todas las letras del tipo a-z (A-Z), los números del 0 al 9 y el resto de símbolos del tipo @  ! # $ + - * / =  % ( ) [ ] y etc...

cadena1 = cadena2Verdadero si cadena1 es igual a cadena2
cadena1 != cadena2
Verdadero si cadena1 no es igual a cadena2
cadena1 < cadena2Verdadero si cadena1 es menor que cadena2
cadena1 > cadena 2Verdadero si cadena1 es mayor que cadena 2
-n cadena1Verdadero si cadena1 no es igual al valor nulo (longitud mayor que 0)
-z cadena1Verdadero si cadena1 tiene un valor nulo (longitud 0)

Comparación de valores numéricos

En este cuadro en específico, solamente utilizamos operadores de comparación para valores numéricos, por lo que dejamos exentos a cualquier otro carácter que no sea escitamente un número, o sus signos de decimales, milésimas y/o etc.

 x -lt yVerdadero si x es menor que y
x -le yVerdadero si x es menor o igual que y
x -eq yVerdadero si x es igual que y
x -ge yVerdadero si x es mayor o igual que y
x -gt yVerdadero si x es mayor que y
x -ne y
Verdadero si x no es igual que y
 


Comprobación de atributos de fichero
El manejo de archivos (muchas veces utilizados como bases de datos), es un aspecto de uso común en la agenda diaria del desarrollador Shell. Debemos recordar que la gran intención de BASH es facilitar las tareas cíclicas (y/o especificas) dentro de nuestro entorno Linux (y Windows recientemente); por tanto debemos manejar al dedillo los mecanismos para manejar adecuadamente los ficheros que alimentaran nuestro guión.

-d
Verdadero si el fichero existe y es un directorio
-e
Verdadero si el fichero existe
-f Verdadero si el fichero existe y es un fichero regular (no un directorio, u otro tipo de fichero especial)
-rVerdadero si tienes permiso de lectura en fichero
-s Verdadero si el fichero existe y no esta vacio
-wVerdadero si tienes permiso de escritura en fichero
 -x Verdadero si tienes permiso de ejecución en fichero (o de búsqueda si es un directorio).
-O Verdadero si eres el dueño del fichero
-GVerdadero si el grupo del fichero es igual al tuyo.
fichero1 -nt fichero2
Verdadero si el fichero1 es mas reciente que fichero2
fichero1 -ot fichero2Verdadero si el fichero1 es mas antiguo que fichero2

Podemos combinar varias condiciones con los símbolos '&&' (AND) y '||' (OR), y negar una condición con '!'. Esto lo veremos con mayor claridad en los siguientes ejemplos.


if/else

La sintaxis de esta construcción es la siguiente:

if "condicion"
then
  "comandos"
[elif "condicion"
then
  "comandos"]
[else
  "comandos"]
fi

Como ya hemos dicho, podemos comprobar los valores de terminación de un comando, y comparar cadenas alfanuméricas/numéricas y atributos de ficheros.

A continuación crearemos un directorio, y verificaremos si fue exitosamente ejecutado el comando.

#!/bin/bash

DIRECTORIO="/tmp/test"
COMANDO="/bin/mkdir $DIRECTORIO

if $COMANDO
then

echo "$DIRECTORIO ha sido creado"
else

echo "$DIRECTORIO no pudo ser creado"
fi

for
La sintaxis de esta construcción es la siguiente:

for nombre [in lista]

do

   comandos que pueden utilizar $nombre

done

Un ejemplo nos aclarara las cosas. Vamos a listar información en el DNS de una lista de direcciones web:

#!/bin/bash 
for HOST in www.hackingballz.com www.google.com www.yahoo.com
do

echo "-----------------------" 
echo $HOST
echo "-----------------------"

/usr/bin/host $HOST

echo "-----------------------" 
done


En este caso obtendríamos un resultado como el siguiente:

[root@ns01 bash]# sh bash.sh
-----------------------
www.hackingballz.com
-----------------------
www.hackingballz.com is an alias for hackingballz.com.
hackingballz.com has address 67.159.35.35
hackingballz.com mail is handled by 10 mail.hackingballz.com.
-----------------------
-----------------------
www.google.com
-----------------------
www.google.com is an alias for www.l.google.com.
www.l.google.com has address 64.233.167.99
www.l.google.com has address 64.233.167.104
www.l.google.com has address 64.233.167.147
-----------------------
-----------------------
www.yahoo.com
-----------------------
www.yahoo.com is an alias for www.yahoo-ht3.akadns.net.
www.yahoo-ht3.akadns.net has address 69.147.114.210
-----------------------
[root@ns01 bash]#

Sin lugar a duda el potencial de los bucles con FOR son prácticamente ilimitadas. Al igual como lo vimos en el ejemplo anterior, fácilmente podemos recorrer una lista de HOST, y obtener los resultados deseados.

A partir de ello podemos pensar en un sin número de agregados, como por ejemplo incluir la funcionalidad de un archivo de texto que nos deje alimentar el guion sin necesidad de escribirlo directamente... Todo depende del escenario en que debamos utilizar sus capacidades.

¿Practico verdad?

while
La sintaxis de while es la siguiente:

while condicion

do

  comandos

done

Un ejemplo simple con while en donde escribimos el valor de una variable 5 veces, después de incrementar repetidamente su valor:

#!/bin/bash

NUM=0

while [ $NUM -le 5 ]; do

    echo "\$NUM: $NUM"

    let NUM=$NUM+1

done
Con while repetiremos una lista de comandos siempre que la condición sea cierta. Hay que recordar que con while se comprueba la condición antes de ejecutar los comandos, con lo cual puede que no se ejecuten ni una sola vez. También disponemos de until, cuyo funcionamiento es similar a while, solo que en esta ocasión la condición sera negada (repetir mientras condición sea falsa, en vez del repetir mientras condición sea cierta que sería un while).

El uso en el caso de until es el siguiente:

until condicion; do

   comandos

done

El ejemplo de uso de until, será prácticamente el mismo que el utilizado el while:
#!/bin/bash

NUM=0

until [ $NUM -gt 5 ]; do

    echo "\$NUM: $NUM"

    let NUM=$NUM+1

done

case
La sintaxis de esta construcción es la siguiente:

case expresion in

     caso_1 )

        comandos;;

     caso_2 )

                    comandos;;

     ......

esac  

Un ejemplo simple con case para aclarar las cosas:


#!/bin/bash


for NUM in 0 1 2 3

do

  case $NUM in

      0)

                      echo "\$NUM es igual a cero";;

      1)

                      echo "\$NUM es igual a uno";;

      2)

                      echo "\$NUM es igual a dos";;

      3)

                      echo "\$NUM es igual a tres";;

  esac

done


select
La sintaxis de esta construcción es la siguiente:

select nombre [in lista]

do

  comandos que pueden utilizar $nombre

done

Un ejemplo simple para aclarar las cosas.
  
#!/bin/bash


select OPCION in opcion_1 opcion_2 opcion_3

  do

  if [ $OPCION ]; then

      echo "Opcion elegida: $OPCION"

      break

  else

      echo "Opcion no valida"

  fi

done
     Hasta aquí llegamos en esta entrega… Sabemos que hasta el momento ha sido la más larga, no obstante hemos cubierto una de las partes más esenciales de todo lo que podemos decir acerca de BASH.