Bash incluye lo que cualquier lenguaje de programación necesita, las comprobaciones condicionales y los ciclos.
Una comprobación(test) es (test en español se traduce como prueba), como su nombre lo dice simplemente una función que se usa para verificar que determinada condición se cumpla (o bien que no); Mientras que un ciclo es un conjunto de instrucciones que se repitan mientras o hasta que la condición se cumpla.
La estructura condicional sirve para comprobar si se ejecuta un bloque de código cuando se cumple una cierta condición. Pueden anidarse varias estructuras dentro del mismo bloques de código, pero siempre existe una única palabra fi para cada bloque condicional.
Lo más básico. If then:
La estructura básica de este condicional va de la siguiente manera
[color=#000000]if expresion;
then
bloque;
fi[/color]
Como podemos ver el if se cierra con fi que al parecer un juego de palabras es fácil de recordar. Así tenemos que si se cumple la condición entraría por el then y finalizaría. Veamos un ejemplo.
[color=#000000]#! /bin/bash
clear
read -p "Cuanto es 9 * 9 " res
mult=$(echo "9*9" | bc -l)
if test $res == $mult
then
echo "El resultado es correcto"
fi[/color]
Explicación: Como podemos ver este script al ser ejecutado nos pide el resultado de la multiplicación de 9 y 9 y lo guarda en la variable $res, luego utilizamos lo que vimos en el capitulo anterior de operaciones aritméticas con bc para declarar la variable $mult. Algunos dirán: “¿No era más fácil decir que $mult= 8?” pues si, pero de esta manera practicamos lo de las operaciones aritméticas, lo de guardar comandos en variables y además así me parece más divertido que un insípido 81. Luego de esto entramos en el condicional y decimos que si se cumple la condición (Que la variable $res es igual a la variable $mult) entonces (then) mostramos en pantalla el mensaje “El resultado es correcto”.
Como vemos donde comienza el condicional if utilizamos la función test que como dijimos anteriormente nos verifica si se cumple la condición. Otra manera de hacer esto sin el test seria:
[color=#000000]if [ $res == $mult
]
then
echo "El resultado es correcto"
fi[/color]
Nota: Como vemos los corchetes remplazan el test. Pero cuidado, es importante respetar los espacios, si no no funciona. If (espacio) [ (espacio) condición (espacio) ].
Ahora bien, para los que ya se han preguntado “¿Y que pasa si no doy el resultado que es?” Si dejamos el script como esta simplemente no hará nada. “Pero yo quiero que me responda si me equivoco”, ok, para eso tenemos el else y funciona de la siguiente manera.
[color=#000000]#! /bin/bash
clear
read -p "Cuanto es 9 * 9 " res
mult=$(echo "9*9" | bc -l)
if [ $res == $mult
]
then
echo "El resultado es correcto"
else
echo "Te has equivocado, el resultado es $mult"
fi[/color]
En español seria algo como: Si (if) lo que tu escribiste por el terminal ($rest) es igual a lo que es el verdadero resultado de 9 * 9 ($mult) entonces (then) muestra el mensaje “El resultado es correcto” si no (else) muestra el mensaje “Te has equivocado, el resultado es el verdadero valor de 9*9 ($mult)”
Ahora vamos a ponerle algo más de sabor al asunto. ¿Que tal si la persona al poner un numero cercano al resultado verdadero nos diga que estamos cerca.? Vamos a ello
[color=#000000]#! /bin/bash
clear
read -p "Cuanto es 9 * 9 " res
mult=$(echo "9*9" | bc -l)
if [ $res == $mult ]
then
echo "El resultado es correcto"
elif [ $res == 80 ] || [ $res == 82 ]
then
echo "Estuviste cerca pero no"
else
echo "Te has equivocado, el resultado es $mult"
fi[/color]
Lo que se ve nuevo aquí es el elif y dentro de este probamos si la variable $res es igual a 80 o igual a 82 para el o usamos el operador lógico || entonces en español seria algo como: si (if) la variable $res es igual a la variable $mult entonces (then) muestra el mensaje “El resultado es correcto” pero si (elif) la variable $res es igual a 80 o (||) aigual a 82 muestra el mensaje “Estuviste cerca pero no” si no se cumple ninguna de las condiciones (else) muestra el mensaje “Te has equivocado, el resultado es $mult (81)”.
Veamos otro ejemplo que comprueba si existe la ruta a un directorio y muestra lo que tiene..
[color=#000000]#! /bin/bash
clear
read -p "Ruta al directorio: " ruta
if [ -e $url ]
then
echo "Si es un directorio y contiene: "
ls -l $ruta
else
echo "No es un directorio"
fi[/color]
Explicación: Como siempre limpiamos la pantalla, solicitamos la ruta al directorio (Ejemplo: /var/www/joomla/) y la guardamos en la variable $ruta luego utilizamos -e para comprobar que la ruta al directorio existe y si se cumple la condición entonces muestra el mensaje “Si es un directorio y contiene: ” y a continuación con ls -l mostramos la lista de todo lo que contiene el directorio, sencillo ¿no?.
Case Esac
Este tipo de sentencia, seria al equivalente al swicht en lenguaje C. Como otro tipo de estructura seria el equivalente a una serie de if anidados, con estos podría obtener el mismo resultado, la diferencia es que usando la sentencia case, el algoritmo es mas ordenado y completo.
vamos a ver el mismo ejemplo de hace rato pero con case:
[color=#000000]#! /bin/bash
clear
read -p "Cuanto es 9 * 9 " res
case $res in
81)
echo "El resultado es correcto"
;;
80182)
echo "Estuviste cerca pero no"
;;
*)
echo "Te has equivocado, el resultado es 81"
;;
esac[/color]
Explicación: Igual que en el ejemplo anterior pedimos que se introduzca un número por la terminal y lo guardamos en la variable $res y básicamente decimos que en caso de que la variable $res sea 81 me muestre el mensaje “El resultado es correcto”, en caso de que sea 80 u 82 “Estuviste cerca pero no” y en caso de que sea otro numero “Te has equivocado, el resultado es 81” aquí vemos el uso del operador binario | para comprobar si la variable $res es 80 u 82. El asterisco * en este caso es para indicar todo lo demas.
El siguiente ejemplo nos dice que tipo de tecla hemos presionado.
[color=#000000]#! /bin/bash
clear
read -n 1 -p "Pulsa cualquier tecla " tecla
clear
case $tecla in
[a-z,A-Z])
echo "Has introducido una letra"
;;
[0-9])
echo "Has introducido un numero "
;;
*)
echo "Has introducido un caracter especial"
;;
esac[/color]
Explicación: con la opción -n del comando read delimitamos la cantidad de caracteres que se pueden ingresar a 1 y guardamos el valor en la variable $tecla luego decimos que encaso de que la tecla presionada este entre la a y la zeta, mayúscula o minúscula [a-z,A-Z] muestre el mensaje “Has introducido una letra”, en caso de que sea un numero del 0 al 9 [0-9] muestre el mensaje “Has introducido un numero” y en caso contrario * muestre el mensaje “ Has introducido un carácter especial”.
Select
Para no tener que estar haciendo tantos echo y tener nuestros scripts mas ordenados, el bash nos ofrece un comando bastante útil, se trata de select, veamos como funciona.
[color=#000000]select variable in opcion1 opcion2
do
case $variable in
opcion1)
comando
;;
opcion2)
comando
;;
*)
comando
;;
esac
done[/color]
Ahora en funcionamiento con el siguiente script que nos permite elegir entre las opciones listar o salir.
[color=#000000]#! /bin/bash
clear
dir="/var/www/"
select opcion in lista salir
do
case $opcion in
lista)
ls -l $dir
;;
salir)
break
;;
*)
echo "Opcion incorrecta"
;;
esac
done[/color]
Explicación: declaramos la variable $dir como la ruta al directorio de nuestro servidor local /var/www/ y solicitamos que se introduzca la opción que se desea (1 lista o 2 salir). Para ello select nos da el prompt #? luego generamos la condición en caso de que se introduzca 1 se hará una lista del directorio y en caso de que se introduzca 2 se saldrá del script en caso de que se presione otra tecla se muestra el mensaje “Opción incorrecta”.
Recuerdan nuestro script para saber si un directorio existe? Vamos a mejorarlo y darle opciones
[color=#000000]#! /bin/bash
clear
read -p "Ruta al directorio: " ruta
if [ -d $ruta ]
then
PS3="$ruta Si es un directorio. Escoge una opcion: "
select opt in lista salir
do
case $opt in
lista)
ls -l $ruta
break
;;
salir)
break
;;
*)
echo "Opcion Incorrecta"
;;
esac
done
else
echo "$ruta No es un directorio"
fi[/color]
Explicación: Guardamos la ruta que obtenemos por consola en la variable $ruta, creamos la primera condición; si la variable $ruta es un directorio entonces muestra el mensaje “Si es un directorio. Escoge una opcion: “ la variable global PS3 es algo parecido al read -p, en otro capitulo lo explicaremos bien, por ahora sabemos que nos hace escoger entre las opciones 1 y 2, lista y salir respectivamente, en caso de que escojamos 1 hará una lista con ls -l de la ruta incluid en la variable $ruta y saldrá, en caso de que la opción se 2 saldrá y en caso contrario nos dará el mensaje “ Opcion Incorrecta”y nos tendremos que ingresar 1 o 2 para continuar ahora en caso de que en un principio la ruta que hayamos puesto en la variable $ruta no sea valida nos dirá que “$ruta No es un directorio”.
El Clásico For
El ciclo for es ampliamente usado en programación en la mayoría de los lenguajes, en el cual por cada elemento en determinada variable se repetirán determinadas acciones, esto hasta que lo haya hecho con todos los elementos indicados, entonces el ciclo habrá terminado y solo entonces.
Se puede utilizar de las siguientes formas
[color=#000000]for i in var1 var2 var3 var4
do
echo "Esa es la variable $i"
done[/color]
el valor de i se va sustituyendo por el valor de las variables en las que esta iterando así que el resultado seria
[color=#000000]Esta es la variable var1
Esta es la variable var2
Esta es la variable var3
Esta es la variable var4[/color]
Otra manera:
[color=#000000]for i in `seq 1 10`
do
echo $i
done[/color]
En este caso se pide iterar en los números comprendidos del 1 10 así que el bucle se ejecutara hasta llegar a 10 mostrando los números del 1 al 10
[color=#000000]for ((i=1;i<=20;i++))
do
echo "Prueba"
done[/color]
Esta otra manera, que tambien es bastante usada en otros lenguajes, dice que la variable a evaluar es igual a x numero y menor o mayor que otro numero y se manda a auto-incrementar o auto-disminuir. En este caso la variable $i es igual 1 pero menor que 20 y se manda a auto-incrementar lo cual repetirá el comando echo “Prueba” Hasta que la variable $i llegue a 20.
Veamos un ejemplo. Supongamos que tenemos 10 directorios en una carpeta con nombres 1, 2, 3, etc y en uno de esos directorios hay un archivo llamado prueba.txt. Hagamos un script para conseguir ese archivo y poder borrarlo
[color=#000000]#! /bin/bash
clear
for ((i=1;i<=10;i++))
do
if [ -e /home/santiago/prueba_sh/prueba/$i/prueba.txt ]
then
cd /home/santiago/prueba_sh/prueba/$i
pwd
select opt in borrar salir
do
case $opt in
borrar)
rm prueba.txt
break
;;
salir)
break
;;
esac
done
fi
done[/color]
Explicación: primero decimos que la variable $i que será nuestro contador es igual a 1 y menor o igual a 10, de esta manera nos iterara entre el 1 y el 10 luego la mandamos a auto-incrementarse con el operador ++ luego verificaremos que la ruta /home/santiago/prueba_sh/prueba/$i/prueba.txt sea valida, donde $i es el nombre del directorio y cuando se cumpla la condición entrara al directorio con cd mostrara la ruta con pwd y luego nos dará la opción de eliminar el archivo (1) o salir (2) si ingresamos 1 borrara el archivo con rm y saldrá del script, si presionamos 2 saldrá del script.
While
While es una instrucción de control que sirve para generar bucles, en los cuales grupos de instrucciones se ejecutan de forma repetida hasta que se cumpla una condición. Cabe destacar que while, primero comprobará si se cumple la condición y si se cumple y sólo si se cumple entonces pasará a ejecutar secuencialmente las instrucciones contenidas entre do y done.
Cada vez que se ejecuta un bucle completo (paso de bucle) vuelve a verificar si se cumple la condición antes de volver a ejecutar otro paso de bucle.
Ejemplo de uso:
[color=#000000]while [ condicion ]
do
accion
done[/color]
Las acciones entre "do" y "done" se repetirán secuencialmente mientras se cumpla la "condición lógica". Cuando la "condición lógica" deje de ser verdadera, no se ejecutará ninguna "acción". Por ejemplo:
[color=#000000]#! /bin/bash
clear
limite=5
i=0
while [ $limite -ge $i ]
do
echo "Accion $i ejecutada"
let i=$i+1
done[/color]
Explicación: Primero guardamos en una variable $limite un valor numérico, en este caso 5, y le damos valor a la variable $i que sera nuestro contador. Decimos que mientras se cumpla la condición de que la variable $limite mayor o igual que la variable $i se mostrara el mensaje “ Accion $i ejecutada” y nuestro contador aumentara 1, el resultado de este script seria algo como:
[color=#000000]Accion 0 ejecutada
Accion 1 ejecutada
Accion 2 ejecutada
Accion 3 ejecutada
Accion 4 ejecutada
Accion 5 ejecutada[/color]
Vemos que cuando la variable $i llega a 5 muestra por ultima vez el mensaje y se detiene el script, esto es porque al aumentar 1 valor mas,$i pasa a ser igual a 6 y como ya dijimos $limite es igual a 5 esto quiere decir que la condición de que $limite sea mayor o igual a $i deja de cumplirse por lo tanto se sale del bucle.
Veamos el ejemplo de la serie fibonacci con while
[color=#000000]#! /bin/bash
clear
read -p "Limite: " num
a=1
b=1
count=1
echo "Serie Fibonacci"
while [ $count -le $num ]
do
echo $b
let b=$b+$a
let a=$b-$a
let count=$count+1
done
exit[/color]
Pedimos un numero entero para guardarlo en la variable $num como limite declaramos las variables $a y $b que serán igual a 1 y la variable $count que sera nuestro contador y sera igual a uno. Luego iniciamos el bucle y ponemos como condición para que la variable $count sea menor o igual que la variable $num, mientras esta condición se cumpla se mostrara el valor de $b luego $b sera igual a su valor mas el valor de $a y $a sera igual a $b menos su propio valor, $count sera igual a su valor mas uno y se repetirá esto hasta que el contador llegue al valor de $num. Digamos que $num es 10, entonces el resultado sera algo como esto:
[color=#000000]Serie Fibonacci
1
2
3
5
8
13
21
34
55
89[/color]
Until
Until es igual que while pero se diferencia en que ahora el bucle se ejecuta mientras la condición sea falsa.
[color=#000000]#! /bin/bash
clear
num=50
until [ $num -eq 76 ]
do
echo "numero: $num"
num=`expr $num + 1`
done[/color]
En este ejemplo declaramos la variable $num con valor 50 y decimos que hasta que $num sea igual a 76 mostrara “numero: $num” y el valor de $num sera igual a su valor mas 1. Con esto obtendremos algo como esto.
[color=#000000]numero: 50
numero: 51
numero: 52
numero: 53
numero: 54
numero: 55
numero: 56
numero: 57
numero: 58
numero: 59
numero: 60
numero: 61
numero: 62
numero: 63
numero: 64
numero: 65
numero: 66
numero: 67
numero: 68
numero: 69
numero: 70
numero: 71
numero: 72
numero: 73
numero: 74
numero: 75[/color]
Vamos a ver un Script Interesante que se me ocurrió para quitarme la odiosa tarea de crear un archivo para cada script hecho para estos tutoriales con los comandos por consola o por la interfaz. Creé un script que solo me solicita el nombre del archivo para crearlo, escribir la primera linea con #! /bin/bash darle permisos de ejecución y abrirlo listo para editar.
#! /bin/bash
cd ~/prueba_sh/
clear
read -p "Nombre del archivo con su extensión: " fileName
if [ -e /home/santiago/prueba_sh/$fileName ]
then
echo "El archivo $fileName ya existe"
else
> $fileName
echo "#! /bin/bash" > $fileName
sudo chmod +x $fileName
gedit $fileName &
fi
Explicación: Me posiciono en el directorio donde estoy creando mis scripts que en este caso es prueba_sh, pido que se introduzca el nombre del archivo con todo y extensión y se guarda en la variable $fileName. Luego comprobamos si el archivo existe dentro del directorio en el que estamos creándolo, si existe se muestra el mensaje “ El archivo $fileName ya existe” si no procedemos a crear el archivo, le ponemos su primera linea #! /bin/bash pasamos a darle permisos de ejecución con chmod y lo abrimos con el editor gedit listo para trabajar en él.
Hasta aquí por ahora con todo esto de los condicionales y los bucles.. Espero que les sea de utilidad.


