Tracks
/
Bash
Bash
/
Temario
/
Condicionales
Co

Condicionales en Bash

{one: "1 ejercicio", many: "%{count} ejercicios", other: "%{count} ejercicios"}

Acerca de Condicionales

La veracidad en Bash

Bash no tiene el concepto de valores booleanos. Hay strings y números, y arrays de strings o números. Entonces, ¿cómo tratan los comandos condicionales lo verdadero y lo falso?

El estado de salida

Los comandos producen un estado de salida cuando terminan. Un estado de salida es un número entero entre 0 y 255, ambos incluidos. Bash considera que un estado de salida cero representa éxito. Cualquier otro estado de salida representa fracaso.

Esto se aplica a todos los comandos, incluidos los comandos integrados de Bash, las palabras clave y las funciones.

El comando «if»

La sintaxis básica del comando if es

if CONDITIONAL_COMMANDS; then TRUE_COMMANDS; else FALSE_COMMANDS; fi

Empieza por if; los comandos de la condición se separan de los comandos «de éxito» con then; y termina con fi. La cláusula else es opcional.

CONDITIONAL_COMMANDS puede ser un único comando o puede ser una lista de comandos.

Se ejecutan los CONDITIONAL_COMMANDS y

  • si el estado de salida es cero (éxito), se ejecutan los TRUE_COMMANDS.
  • si el estado de salida no es cero (fracaso), se ejecutan los FALSE_COMMANDS, si están presentes.

Se pueden escribir ramas en cascada con elif

if CONDITIONAL_COMMANDS
then TRUE_COMMANDS
elif CONDITIONAL_COMMANDS_2
then TRUE_COMMANDS_2
# more elif branches ...
else FALSE_COMMANDS
fi

Debe haber un punto y coma o un salto de línea antes de las palabras then, elif, else y fi.

Para insistir: es el estado de salida de los comandos condicionales lo que controla el flujo. Por ejemplo, grep devuelve 0 si encuentra una coincidencia y 1 si no la encuentra. La opción -q suprime la salida y solo produce el estado de salida.

if grep -q "my pattern" my_file; then echo "the pattern is found in the file"; fi

Los comandos «[» y «test»

No hay ninguna sintaxis especial en torno a los CONDITIONAL_COMMANDS. Puede que estés acostumbrado a ver instrucciones if con este aspecto:

if [ "$password" = "secure" ]; then
    echo "Welcome!"
fi

[ no es una sintaxis especial. Es un comando que evalúa la expresión condicional y termina con un estado de éxito o de fracaso. Como en todos los comandos, se requiere un espacio en blanco entre él y sus argumentos.

En realidad, [ es un sinónimo del comando test. Son exactamente lo mismo, salvo que el último argumento de [ debe ser ].

Expresiones condicionales

Dentro de [ y ] escribes una expresión condicional. Algunas expresiones condicionales típicas son:

[ -f "$filename" ]             # file operations
[ "$string1" = "$string2" ]    # string comparisons
[ "$num1" -eq "$num2" ]        # arithmetic comparisons

Hay muchas más operaciones disponibles; se enumeran en la sección Expresiones condicionales de Bash del manual.

Note

En los ejemplos anteriores, fíjate en que todas las variables están entrecomilladas. Los comandos test y [ son comandos normales, en los que los argumentos están sujetos a la división de palabras y a la expansión de nombres de archivo como en cualquier otro comando.

Es importante señalarlo porque las expresiones condicionales se evalúan de forma distinta según cuántos argumentos proporciones:

  • 0 argumentos: el estado de salida no es cero (fracaso)
  • 1 argumento: el estado de salida es cero (éxito) si el argumento no está vacío, y no es cero si está vacío.
  • 2 argumentos: el primer argumento debe ser un operador unario (como [ -z "$name" ]), o un ! (que niega el estado de la prueba de 1 argumento)
  • y más.

Puedes obtener resultados inesperados si olvidas entrecomillar:

str=""

# this prints "empty"
if [ -n "$str" ]; then echo "not empty"; else echo "empty"; fi

# leaving the variable unquoted results in incorrect "not empty" output
if [ -n $str ]; then echo "not empty"; else echo "empty"; fi

La palabra clave «[[»

La construcción condicional [[...]] no es un comando, es una palabra clave. Esto significa que, aunque se trata como cualquier otro comando, tiene reglas de análisis sintáctico especiales. Lo especial de [[ es que las variables que se expanden dentro de él no están sujetas a la división de palabras ni a la expansión de nombres de archivo. Eso significa que este comando se comporta como esperas, incluso sin entrecomillar.

if [[ -n $str ]]; then echo "not empty"; else echo "empty"; fi

[[ admite todas las expresiones condicionales que pueden manejar test y [. Además, [[ ofrece

  • el operador de coincidencia de expresiones regulares =~,
  • == y !=, que funcionan como operador de coincidencia de patrones glob,
  • && y || como operadores lógicos (regla de análisis sintáctico especial),
  • < y > como operadores de comparación de strings «a secas» (regla de análisis sintáctico especial: como son símbolos de redirección, en [ hay que escaparlos).

Se considera ampliamente que estas características especiales aportan tantas ventajas que debería usarse [[ de forma exclusiva. (Por ejemplo, la Google Shell Style Guide).

El comando «case»

case es otro comando de control de flujo. Es como una instrucción «switch» de otros lenguajes.

case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac

La WORD se compara con cada PATTERN. Cuando una coincide, se ejecutan los COMMANDS.

read -p "Guess the secret word: " word
case "$word" in
    secret) echo "Yes, you guessed it!" ;;
    ??????) echo "That's the right number of letters." ;;
    s*)     echo "You guessed the first letter." ;;
    *)      echo "Not even close! Try again." ;;
esac

Cada cláusula de COMMANDS debe terminar con dos puntos y coma, ;;.

Note
  1. Existen alternativas que permiten continuar con la ejecución de los siguientes comandos y que la coincidencia de patrones siga buscando. Consulta el manual para más detalles.
  2. Recuerda que hablamos de los patrones en la sección Expansión de nombres de archivo del concepto Entrecomillado.
Editar en GitHub El enlace se abre en una nueva ventana o pestaña