Breve tutorial con ejemplos de cómo funcionan y cuando deben ser utilizados bloques condicionales if y los bucles while/for en programación Bash.
Una de las tareas esenciales de la programación es poder ramificar las tareas o instrucciones de programas, dependiendo de una determinada condición. Con ello conseguimos que nuestros programas se comporten de forma diferente dependiendo de uno o más valores.
Condicionales
En Bash utilizamos el bloque condicional if
para evaluar una condición y está puede ser evaluada como true o false. Cuando se evalúa el estado de salida de un condicional y el resultado es 0, la condición será considerada como true.
1 2 3 4 5 6 7 |
#!/bin/bash if grep "127.0.0.1" /etc/hosts; then echo "Host Ok" else echo "Error: 127.0.0.1 no existe en /etc/hosts" fi |
Al igual que en otros lenguajes de programación, en Bash Scripting utilizamos la indentación, pero la forma de escribir el condicional puede diferir.
El comando test
, nos permite evaluar si las condiciones tienen valor de salida 0 (cuando son true) o valor de salida 1 (cuando son false). Utilizamos el parámetro -n con el comando test para comprobar si la variable a comprobar está vacía o no. Veamos un ejemplo:
1 2 |
$ echo $PATH $ if test -n "PATH"; then echo "PATH Ok"; fi |
Podemos utilizar el comando test de otra forma, para que su escritura se asemeje a otros lenguajes de programación. Si utilizamos esta sintaxis necesitamos incluir espacios antes y después de escribir los corchetes. Omitimos escribir el comando test ya que los corchetes son un alias de este.
1 |
if [ -n "PATH" ]; then echo "PATH Ok"; fi |
Para saber más sobre el comando test, puedes usar el comando man test.
Bucles while
Al igual que otros lenguajes de programación (Python, PHP, etc …), podemos realizar iteraciones mientras una condición sea cierta (true) haciendo uso de un bucle while
.
1 2 3 4 5 6 7 |
#!/bin/bash x=1 while [ $x -le 5 ]; do echo "Iterando número $x" ((x+=1)) done |
La forma de escribir una condición while es la misma que una condición if. Utilizando el operador -le, le indicamos que x tiene que ser menor o igual que 5. El bucle comenzará con la palabra clave do y termina con la palabra clave done. Para poder incrementar el valor de x, necesitamos utilizar paréntesis, que nos permite hacer uso de operaciones aritméticas con nuestras variables.
Ahora vamos a crear un bucle while un poco más complejo, ejecutando otro script hasta que este sea ejecutado correctamente o falle 5 veces. Esto puede ser útil cuando estamos accediendo a recursos conectados a una red o ficheros que podrían estar bloqueados.
1 2 3 4 5 6 7 8 9 |
#!/bin/bash x=0 comando=$1 while ! $comando && [ $x -le 4 ]; do sleep $x ((x+=1)) echo "Intento #$x" done; |
Para acceder a los parámetros en Bash utilizamos el símbolo del dólar ($) y el número del parámetro introducido que necesitamos.
El comando sleep es importante cuando realizamos este tipo de operaciones ya que permite al sistema recuperarse a la hora de realizar otro intento. Podemos ejecutar el script sobre otro script u otro comando que deseemos, que intentará completarlo hasta 5 veces, hasta que consiga un valor de salida 0.
1 |
$ ./while2.sh ./connect.sh |
Bucles for
En Bash scripting utilizamos los bucles for para iterar elementos que contienen espacios entre ellos. Veamos un ejemplo sencillo:
1 2 3 4 5 |
#!/bin/bash for lenguaje in php java python bash; do echo "Me gusta programar en $lenguaje" done |
1 2 3 4 5 |
./for.sh Me gusta programar en php Me gusta programar en java Me gusta programar en python Me gusta programar en bash |
Hemos visto anteriormente en el tutorial Bash Scripting: Creación de Scripts en Bash y utilización de Variables y Globs, que podemos usar listas de ficheros haciendo uso de globs mediante los símbolos de asterisco e interrogación. Como estas listas están separadas por espacios, podemos usarlos con nuestros bucles for para iterar sobre ellas.
Supongamos que tenemos un sitio web y necesitamos renombrar todos los ficheros con extensión .htm a .html. Existe un comando llamado basename que nos puede ayudar con la tarea. Lo que hace es tomar el nombre del fichero y su extensión para así retornar tan sólo el nombre del fichero.
1 2 3 4 5 6 7 8 9 |
#!/bin/bash dir="./files/" ext="*.htm" for file in $dir$ext; do name=$(basename "$file" .htm) echo "...renombrando $file a: $name.html" mv "$file" "$dir$name.html" done |
1 2 3 4 |
$ ./for2.sh ...renombrando ./files/contact.htm a: contact.html ...renombrando ./files/index.htm a: index.html ...renombrando ./files/who.htm a: who.html |
Otra forma de hacerlo es llamando al comando directamente incluyendo este entre comillas.
1 |
for file in `ls ./files/*.htm`; do |