# Tutorial Bash II


## ¡Hola, internauta! {#hola-internauta}

Hoy quiero traerte un tutorial de **Bash** con contenido más completo, especialmente enfocado en scripting. Porque sí, supongo que para eso estás aquí, ¿no? Para aprender… o quizá solo para reírte un rato con las cosas que se me ocurren decir (aunque qué feo venir solo a reírse de un loquito más). Pero bueno, para eso estoy: para compartir contigo lo mejor de lo mejor. Este es un tutorial que me he sacado de la manga. ¿Que por qué lo hice? Ni yo mismo lo sé a veces, pero aquí estoy, siendo cordial y amigable con ustedes, los que de verdad quieren leerme.

> La curiosidad no mata al gato, lo mete en problemas... ¡pero de los interesantes! 😼
>
> {{< style "text-align: right;" >}}_Raksodiano_{{< /style >}}


## Operadores {#operadores}

En Bash tenemos operadores matemáticos, de comparación y lógicos. Estos nos permiten realizar diversas validaciones según los distintos escenarios que puedan surgir en nuestros scripts. Claro, todo depende de lo que quieras hacer (aunque, si esto te parece mucho, tal vez deberías ir a estudiar humanidades... 😹). Pero si te ves capaz -y yo confío en que sí-, puedes usar estos operadores para crear validaciones tan complejas como tu lógica lo permita. ¿Te animas?


### Matemáticos {#matemáticos}

Usados para realizar operaciones aritméticas básicas.

| Nombre         | Operador | Ejemplo              |
|----------------|----------|----------------------|
| Suma           | +        | echo $(( 1 + 1 ))    |
| Resta          | -        | echo $(( 1 - 1 ))    |
| Multiplicación | \*       | echo $(( 2 \* 2 ))   |
| División       | /        | echo $(( 10 / 2 ))   |
| Módulo         | %        | echo $(( 5 / 2 ))    |
| Potencia       | \*\*     | echo $(( 2 \*\* 3 )) |
| Incremento     | ++       | ((x++))              |
| Decremento     | --       | ((x--))              |


### Comparación {#comparación}

Usados para comparar números o cadenas, comúnmente en estructuras.

| Nombre              | Operador | Ejemplo           |
|---------------------|----------|-------------------|
| Igual               | -eq      | [ "$a" -eq "$b" ] |
| Distinto / No igual | -ne      | [ "$a" -ne "$b" ] |
| Menor que           | -lt      | [ "$a" -lt "$b" ] |
| Menor o igual que   | -le      | [ "$a" -le "$b" ] |
| Mayor que           | -gt      | [ "$a" -gt "$b" ] |
| Mayo o igual que    | -ge      | [ "$a" -ge "$b" ] |


### Lógicos {#lógicos}

Permiten combinar múltiples condiciones.

| Nombre              | Operador | Ejemplo                       |
|---------------------|----------|-------------------------------|
| Negación            | !        | [ ! "$a" = "$b" ]             |
| AND (un "y" lógico) | -a       | [ "$a" -gt 5 -a "$b" -lt 10 ] |
| OR (un "o" lógigo)  | -o       | [ "$a" -gt 5 -o "$b" -lt 10 ] |


## Condicionales {#condicionales}

Estos operadores permiten que tus scripts tomen decisiones basadas en si una condición es verdadera o falsa, dependiendo del resultado de la evaluación definida.


### if {#if}

El comando `if` en **Bash**, que podríamos traducir como un "si", se utiliza para evaluar condiciones dentro de un script. Básicamente, es como hacer una pregunta: "¿Esto es sensual?" Si la respuesta es verdadera, entonces se ejecuta el bloque de código que está dentro del `if`. De lo contrario, el script sigue por otro camino.

La sintaxis básica de un `if` en **Bash** es la siguiente:

```bash
if [ condición ]; then
   # instrucciones si la condición es verdadera
fi
```

Aquí tienes un ejemplo de script para ver cómo funcionaría todo lo que hemos visto hasta ahora. Puedes copiar este código, pegarlo en un archivo (por ejemplo, `mi_sensual_script.sh`) y ejecutarlo desde la terminal. Así podrás practicar con algunos de los conceptos que ya repasamos en el tutorial anterior:

{{< admonition info "Información" false >}}
Sí, un ejemplo de edad... ¿Qué esperabas? ¿¡La receta de pollo del Koronel!? 🍗
{{< /admonition >}}

```bash
# Recuerda iniciar nuestro suculento script
#!/bin/bash

# Con la opción '-n' eliminamos el salto de linea para que el read quede al lado del mensaje
echo -n "Ingresa tú edad: "
read edad

# Hacemos la validación de que su edad sea mayor que 17
# o sea, comenzamos a contrar que sea 18 en adelante
if [ $edad -gt 17 ]; then
  # Este código solo se ejecuta siempre que ingrese un numero supeior a 17
  echo "Ya eres todo un adulto, ya debes de tener pelito allá abajo :V"
fi

echo "Fin del sensual script"
```


### else {#else}

El `else` se traduce como el "sino", y nos permite ejecutar otro bloque de código cuando la condición anterior no se cumple. Como puedes ver en la sintaxis, el `else` forma parte del bloque del `if`.

```bash
if [ condición ]; then
   # instrucciones si la condición es verdadera
else
   # instrucciones si es falsa
fi
```

Ahora vamos a usarlo un poco, para que puedas ver qué ocurre cuando seguimos otro camino, siempre por el buen camino, nada de esos caminos oscuros 😏.

```bash
#!/bin/bash

echo -n "Ingresa tú edad: "
read edad

if [ $edad -gt 17 ]; then
  echo "Ya eres todo un adulto, ya debes de tener pelito allá abajo :V"
else
  # Mientras el numero sea 17 o menor
  echo "Eres un jovencito, gracias por participar"
fi

echo "Fin del super script"
```


### elif {#elif}

El `elif` se utiliza para evaluar una nueva condición, lo que nos permite validar múltiples condiciones de manera secuencial. Además, puede anidarse tantas veces como sea necesario, dándonos la posibilidad de tomar más de una decisión dentro de un mismo bloque.

```bash
if [ condición1 ]; then
    # si condición1 es verdadera
elif [ condición2 ]; then
    # si condición2 es verdadera
else
    # si ninguna se cumple
fi
```

Podemos ver el uso del mismo así, sin miedo a equivocarnos, ¡que el `elif` está para eso, para probar todas las opciones hasta dar con la correcta!, Aunque, ojo, no te pases de "probadita" 😼.

```bash
#!/bin/bash

echo -n "Ingresa tú edad: "
read edad

if [ $edad -lt 0 ]; then
  echo "¿Cómo que edades negativas?, estás loco, ni que fueras un feto >:V"

# Agregamos un poco más de lógica
# Iniciamos que el primer caso sea que su edad sea mayor a 17 y menor a 60
elif [ $edad -gt 17 -a $edad -lt 60 ]; then
  echo "Ya eres todo un adulto, ya debes de tener pelito allá abajo :V"

# En este caso solo validamos que sea mayor que 59
elif [ $edad -gt 59 ]; then
  # Este se ejecuta siempre que sea mayor que 59
  echo "Ya estás bien ruco, ¿qué haces aquí? :V"

# Y por el ultimo caso dejamos que sea por defecto
else
  echo "Eres un jovencito, gracias por participar"

fi

echo "Fin del super script"
```


### case {#case}

El `case` se puede definir como una estructura de control utilizada para realizar la comparación de patrones. Dentro de esta estructura, solo puedes definir una variable y los diferentes valores que puede tomar, ya que **no valida operadores**.

```bash
case $variable in
  patron1)
    # instrucciones
    ;;
  patron2)
    # instrucciones
    ;;
  *)
    # por defecto
    ;;
esac
```

Podemos hacer uso del mismo de esta forma, sin miedo, que el `case` está para hacer comparaciones, no para juzgarte... mucho... 😼

```bash
#!/bin/bash

echo -n "Ingresa el nombre de un animal: "
read animal

case $animal in
  "gato")
    echo "Este animalito es muy bonito y apapachable, solo no lo toques en su pansita"
    ;;
  "perro")
    echo "Este animalito es el mejor amigo del hombre wiii"
    ;;
  "oso")
    echo "Este animalito come gente, así que no te acerques :3"
    ;;
  *)
    echo "Este animalito no lo conozco"
    ;;
esac
```

{{< admonition note "Notita" false >}}
Al hacer las pruebas, te darás cuenta de que solo funcionan `gato`, `perro` y `oso`. Cualquier otra combinación de caracteres, como `Gato`, `GATO` o cualquier variación, no será reconocida, ya que la comparación es sensible... a mayúsculas y minúsculas.
{{< /admonition >}}


## Bucles {#bucles}

Son estructuras que te permiten ejecutar un bloque de comandos repetidamente, mientras se cumpla cierta condición. Estas estructuras son muy útiles cuando necesitas automatizar tareas repetitivas o recorrer elementos sin tener que escribir el mismo código una y otra vez.


### For {#for}

Sirve para recorrer una lista o un rango, ejecutando el mismo bloque de código para cada elemento. Esto nos permite procesar un conjunto finito de valores de forma ordenada y eficiente, sin tener que escribir una instrucción para cada uno.

```bash
for variable in lista/rango
do
  # instrucciones
done
```

Podemos tener varios usos, por ejemplo, recorrer una lista o un rango. Así que aquí tienes este par de ejemplos;


#### Lista {#lista}

```bash
#!/bin/bash

animales="perro gato conejo elefante tigre"

for animal in $animales
do
  echo "animalito: $animal"
done
```


#### Rango {#rango}

```bash
#!/bin/bash

# Te voy a dejar de tareita buscar como se usan los rangos
for i in {1..10}
do
  echo "Vueltica: $i"
done
```


### While {#while}

Este se usa cuando no sabemos cuántas veces debe repetirse el bloque de código, pero queremos que se ejecute mientras se cumpla una determinada condición. Justamente por eso se llama `while`, que se traduce como "mientras", indicando que el código se seguirá ejecutando "mientras" la condición sea verdadera.

```bash
while [ condición ]
do
  # instrucciones
done
```

Hagamos un ejemplo más donde realicemos un conteo de números, y que al llegar a uno específico se detenga. Piensa en esto como: "Mientras sea menor o igual que 10, se ejecuta".

```bash
#!/bin/bash

i=1

# Mientras sea menor igual que 10 se estará ejecutando
while [ $i -le 10 ]
do
  echo "Hola x$i"   # Vamos a llevar la secuencia
  ((i++))           # Usamos un incremento ya comentado arriba
done
```


### Until {#until}

El `until` es similar al `while`, pero se puede traducir como "hasta", por lo que la lógica detrás de su uso es un poco diferente. En lugar de ejecutarse mientras la condición sea verdadera, como en `while`, el bloque de código en `until` se ejecuta "hasta" que la condición se vuelva verdadera.

```bash
until [ condición ]
do
  # instrucciones
done
```

Veamos un ejemplo para entenderlo mejor. Piensa en esto como: "Hasta que sea mayor o igual que 11", el código se seguirá ejecutando.

```bash
#!/bin/bash

i=1

# Se ejecuta hasta que i sea mayor o igual a 11
until [ $i -ge 11 ]
do
  echo "Hola x$i"   # Mostramos el valor actual
  ((i++))           # Incrementamos i
done
```


### Bucles infinitos {#bucles-infinitos}

Ten presente que con todos los bucles que hemos visto hasta ahora pueden surgir problemas de bucles infinitos, es decir, aquellos que se ejecutan de manera indefinida si no se controla bien la condición. Por eso, es importante tener cuidado al escribirlos. Afortunadamente, contamos con dos grandes aliados: `break` y `continue`, que nos ayudan a controlar mejor la ejecución dentro de los bucles.


#### Break {#break}

Veamos el siguiente ejemplo: si definimos una condición que siempre sea verdadera, podemos provocar un bucle infinito. Para evitarlo, usamos `break`, que nos permite forzar la salida del bucle cuando se cumpla cierta condición.

{{< admonition info "Información" false >}}
En el siguiente ejemplo, trata de eliminar el bloque `if` completo, verás que el bucle se ejecutará infinitamente.

Para detenerlo, solo dile: "¡Zorro, no te lo lleves!"... ah no, así no era. ¿Cómo era?... ¡Ah, ya me acordé! Es `Ctrl + C` 😅.
{{< /admonition >}}

```bash
#!/bin/bash

i=1
while [ true ]; do
  echo "Número: $i"

  if [ $i -eq 5 ]; then
    echo "¡Son las 5! me voy a mi casa..."

    # Ejecutamos el break para que rompa el ciclo y pueda salir
    break

  fi

  ((i++))
done
```


#### Continue {#continue}

En algunos casos necesitaremos que el bucle salte cierta iteración bajo una condición específica. Para eso podemos usar `continue`, que nos permite omitir esa vuelta del bucle y pasar directamente a la siguiente. Esto puede ser útil para evitar casos que no nos interesan o incluso para prevenir un posible bucle infinito si no se cumplen ciertas condiciones dentro del ciclo.

{{< admonition info "Información" false >}}
Si ves la salida de este script, notarás que **no aparecerá la línea** `Número: 5`, ya que la saltamos y le sumamos uno al contador en ese punto. Es como cuando te saltas los anuncios con bloqueadores, ¡ni te das cuenta y sigues disfrutando sin interrupciones! 😆... hasta que te bloquean como a mí. 😢
{{< /admonition >}}

```bash
#!/bin/bash

i=1

until [ $i -gt 10 ]; do
  if [ $i -eq 5 ]; then
    ((i++))         # Incrementamos antes de continuar, para saltarnos este caso
    continue        # Saltamos esta vuelta del bucle
  fi

  echo "Número: $i"
  ((i++))
done
```

Sí ves la salida de este script, no saldrá la linea `Número: 5`, esto porque la saltamos e hicimos que se le sumara uno al contador.


## echo "Bye bye" {#echo-bye-bye}

{{< admonition info "Información" false >}}
Todos los scripts de las secciones puedes probarlos sin problema, ya que están hechos con mucho amor para ti 💋. Además, ya los he probado por ti, así que solo tienes que copiar y pegar en tus archivos `.sh` y ¡listo!
{{< /admonition >}}

Bueno, como palabras finales, quiero dejar en claro que este post está escrito con un tono de humor algo curioso y raro, pero con la alegría genuina de poder enseñarte de una forma más amena.

Espero que este contenido te sea útil, ya que mi objetivo es que puedas practicar con el tiempo y desarrollar la curiosidad para investigar e indagar más sobre lo que te interesa. Tal vez estás aquí solo por entretenimiento, y te agradezco que lo estés.

Me gustaría que te sientas cómodo leyendo algo que, además de informarte, te saque una sonrisa. No todo tiene que ser tratado con rigor y seriedad, también podemos disfrutar de contenido que, aunque a veces parezca aburrido o poco interesante, sabemos que es necesario aprender.

Así que nada… vamos improvisando sobre la marcha.

>🙏 *Pensamiento final*
>
>Que **San Ignucio** te proteja del ~software privativo~, <br>
>que tus scripts siempre encuentren su `PATH`, <br>
>y que jamás te falte un buen `grep` para encontrar sentido entre las líneas. <br>
>
>**Recuerda**: <br>
>*"Benditos sean los que comparten su `código`,
>porque de ellos será el reino del `software libre`"*
>
>¡Nos leemos pronto, con terminal abierta y corazón libre! 🐧✨

