Categorías
GNU-Linux Script

Crea y ejecuta tu primer script de Bash Shell

Toma de decisiones con If - Else y Case

Toma de decisiones con declaraciones If Else y Case

En esta parte aprenderás a usar sentencias condicionales en tus scripts bash para hacer que se comporten de forma distinta en diferentes escenarios y casos.

De esta manera puedes construir scripts bash mucho más eficientes y también puedes implementar la comprobación de errores en tus scripts.

Uso de la sentencia if en bash

La construcción más básica en cualquier estructura de toma de decisiones es una condición if. La sintaxis general de una declaración if es:

if [ condición ]; then
  tu código
fi

La sentencia if se cierra con un fi (reverso de if).

Presta atención al espacio en blanco.

  • Debe haber un espacio entre los paréntesis de apertura y cierre y la condición que escribas. De lo contrario, el shell se quejará de un error.
  • Debe haber espacio antes y después del operador condicional (=, ==, <= etc). De lo contrario, verás un error como «se espera un operador unario».

Ahora, vamos a crear un script de ejemplo root.sh. Este script mostrará «Eres root» sólo si se ejecuta el script como el usuario root:

#!/bin/bash

if [ $(whoami) = 'root' ]; then
	echo "Eres root"
fi

El comando whoami devuelve el nombre de usuario. Ya sabés que la sintaxis $(comando)se usa para sustitución y te devuelve la salida del comando.

La condición $(whoami) = 'root' será verdadera sólo si se ha iniciado la sesión como usuario root.

¿No me creés? No hace falta que lo hagas. Comprobalo vos mismo.

Uso de la sentencia if-else en bash

Puede que hayas notado que no obtienes ninguna salida cuando ejecutas el script root.sh como un usuario normal. Cualquier código que quieras ejecutar cuando una condición if es evaluada como falsa puede ser incluida en una sentencia else

#!/bin/bash

if [ $(whoami) = 'root' ]; then
	echo "Eres root"
else
	echo "No eres root"
fi

Ahora, cuando ejecutes el script como usuario normal, se te recordará que no eres el todopoderoso usuario root:

$ ./root.sh
No eres root

Uso de la sentencia else if en bash

Puedes utilizar una sentencia elif (else-if) siempre que quieras probar más de una expresión (condición) al mismo tiempo.

Por ejemplo, el siguiente script bash edad.sh toma tu edad como argumento y emitirá un mensaje significativo que corresponde a tu edad

#!/bin/bash

EDAD=$1

if [ $EDAD -lt 13 ]; then
	echo "Eres un niño."
elif [ $EDAD -lt 20 ]; then
	echo "Eres un adolescente."
elif [ $EDAD -lt 65 ]; then
	echo "Eres un adulto."
else
	echo "Eres un anciano."
fi

Ahora ejecuta varias veces el script edad.sh para probar con diferentes edades:

$ ./edad.sh 11
Eres un niño.
$ ./edad.sh 18
Eres un adolescente.
$ ./edad.sh 44
Eres un adulto.
$ ./edad.sh 70
Eres un anciano.

Observa que he utilizado -lt (less than – menos que) para evaluar la condición con la variable $EDAD.

También ten en cuenta que se pueden tener múltiples declaraciones elif pero sólo una declaración else en una construcción if y debe ser cerrada con un fi.

Uso de sentencias if anidadas en bash

You can also use an if statement within another if statement. For example, take a look at the following clima.sh bash script:

#!/bin/bash

TEMP=$1

if [ $TEMP -gt 8 ]; then
	if [ $TEMP -lt 15 ]; then
		echo "Hace frío."
	elif [ $TEMP -lt 20 ]; then
		echo "Está agradable."
	else
		echo "Hace calorcito."
	fi
else
	echo "Está helando afuera ..."
fi

El script toma cualquier temperatura como argumento y luego muestra un mensaje que refleja cómo está el tiempo. Si la temperatura es mayor que diez, entonces se evalúa la declaración anidada (interna) if-elif. Hagamos unas cuantas ejecuciones del script para ver cómo funciona:

$ ./clima.sh 6
Está helando afuera ...
$ ./clima.sh 11
Hace frío.
$ ./clima.sh 16
Está agradable.
$ ./clima.sh 30
Hace calorcito.

Uso de la sentencia Case en bash

También puede utilizar las sentencias case en bash para reemplazar las múltiples sentencias if, ya que a veces son confusas y difíciles de leer. La sintaxis general de una construcción case es la siguiente:

case "variable" in
	"pattern1" )
		Comando … ;;
	"pattern2" )
		Comando … ;;
	"pattern2" )
		Comando … ;;
esac

Presta atención.

  • Los patrones van siempre seguidos de un espacio en blanco y ).
  • Los comandos van siempre seguidos de un doble punto y coma ;;. El espacio en blanco no es obligatorio antes de.
  • Las sentencias Case terminan con esac (reverso de case).

Las sentencias Case son particularmente útiles cuando se trata de coincidencias de patrones o expresiones regulares. Para demostrarlo, observa el siguiente script bash caract.sh:

#!/bin/bash

CARACT=$1

case $CARACT in
[a-z])
echo "Minúsculas." ;;
[A-Z])
echo "Mayúsculas." ;;
[0-9])
echo "Número." ;;
*)
echo "Carácter Especial."
esac

El script toma un carácter como argumento y muestra si es mayúscula/minúscula, número o un carácter especial.

$ ./caract.sh a
Minúsculas.
$ ./caract.sh Z
Mayúsculas.
$ ./caract.sh 7
Número.
$ ./caract.sh $
Carácter Especial.

Observa que he utilizado el símbolo de asterisco (*) para definir el caso predeterminado, que es el equivalente a una sentencia else en una condición if.

Condiciones de prueba en bash

Existen numerosas condiciones de prueba que puede utilizar con las sentencias if. Las condiciones de prueba varían si estás trabajando con números, cadenas o archivos. Piensa en ellas como operadores lógicos en bash.

He incluido algunas de las condiciones de prueba más populares en la siguiente tabla:

Condición Equivalente
$a -lt $b $a < $b
$a -gt $b $a > $b
$a -le $b $a <= $b
$a -ge $b $a >= $b
$a -eq $b $a es igual a $b
$a -ne $b $a no es igual a $b
-e $ARCHIVO $ARCHIVO existe
-d $ARCHIVO $ARCHIVO existe y es un directorio.
-f $ARCHIVO $ARCHIVO existe y es un archivo normal.
-L $ARCHIVO $ARCHIVO existe y es un enlace simbólico.
$CADENA1 = $CADENA2 $CADENA1 es igual a $CADENA2
$CADENA1 != $CADENA2 $CADENA1 no es igual a $CADENA2
-z $CADENA1 $CADENA1 está vacía

Por suerte, no necesitas memorizar ninguna de las condiciones de la prueba porque puedes buscarlas en la página man de test:

$ man test

Vamos a crear un script llamado tipoarchivo.sh que detecta si un archivo es un archivo normal, un directorio o un enlace simbólico:

#!/bin/bash

if [ $# -ne 1 ]; then
	echo "Error: Número de argumentos inválido"
 	exit 1
fi

file=$1

if [ -f $archivo ]; then
	echo "$archivo es un archivo normal."
elif [ -L $archivo ]; then
	echo "$archivo es un enlace simbólico."
elif [ -d $archivo ]; then
	echo "$archivo es un directorio."
else
	echo "$archivo does not exist"
fi

He mejorado un poco el script añadiendo una comprobación del número de argumentos. Si no hay argumentos o hay más de un argumento, el script mostrará un mensaje y saldrá sin ejecutar el resto de las sentencias del script.

Hagamos unas cuantas ejecuciones del script para probarlo con varios tipos de archivos:

$ ./tipoarchivo.sh clima.sh
clima.sh es un archivo normal.
$ ./tipoarchivo.sh /bin
/bin es un enlace simbólico.
$ ./tipoarchivo.sh /var
/var es un directorio.
$ ./tipoarchivo.sh 
Error: Número de argumentos inválido

Bonus: Declaración Bash if else en una línea

Hasta ahora todas las sentencias if else que has visto han sido utilizadas en un script bash adecuado. Esa es la forma correcta de hacerlo pero no estás obligado a ello.

Cuando sólo quieres ver el resultado en el propio shell, puedes usar las sentencias if else en una sola línea en bash.

Supongamos que tienes este script bash.

if [ $(whoami) = 'root' ]; then
	echo "Eres root"
else
	echo "No eres root"
fi

Puedes utilizar todas las sentencias if else en una sola línea como la siguiente:

if [ $(whoami) = 'root' ]; then echo "root"; else echo "no root"; fi

Puedes copiar y pegar lo anterior en la terminal y ver el resultado por tu cuenta.

Básicamente, sólo tienes que añadir punto y coma después de los comandos y luego añadir la siguiente declaración if-else.