Aprendemos a usar grep en el aula: guía breve pero fundamental.



Aprendemos a usar grep en el aula: guía breve pero fundamental.



grep como legado UNIX puro.


Antes de entrar en opciones y ejemplos, nos vamos a detener tan solo un minuto en lo que representa grep dentro del ecosistema UNIX.
No es solo una herramienta para buscar texto, sino una pieza clave, un importante legado respecto a una idea mucho más grande que el comando en sí... Un concepto inherente a esta orden que debería estar recordándonos permanentemente cómo programar bien.
Dentro del ecosistema UNIX, los programas bien hechos no están pensados para hacerlo todo, sino para hacer una sola cosa bien (principio KISS) y para poder combinarse entre sí. Esta combinación se logra a través de las tuberías (pipes), en las cuales la salida de un comando (o programa), se convierte en la entrada de otro.
grep encarna ese principio de forma excelente, porque no necesita saber de dónde vienen los datos ni qué se hará con ellos después. Simplemente recibe texto, filtra según un criterio y devuelve el resultado. Esta simplicidad es lo que le permite integrarse en flujos más complejos: filtrar el "ruido innecesario" en la salida de otros comandos, analizar archivos de "logs" en tiempo real, procesar listados generados por otros comandos o inspeccionar grandes volúmenes de información sin necesidad de herramientas pesadas.
En este sentido, utilizar grep es empezar a pensar con cabeza UNIXera, en donde construir soluciones a partir de piezas pequeñas encadenadas con absoluta precisión, es... mandatory!
Es una forma de trabajar en la cual la verdadera potencia no radica en un comando o programa individual, sino en la manera en que estos se conectan entre sí.


Prefacio.

grep es una de esas herramientas que aplicada de manera directa en la terminal puede parecer simple, pero que rápidamente se va volviendo indispensable cuando se empieza a trabajar con archivos de "logs" o directamente con código. En esencia, hace algo muy concreto: buscar texto. Sin embargo, la forma en la cual lo hace (tanto como también las opciones que ofrece) son determinantes al utilizarlo como filtro básico o como potente herramienta de diagnóstico.


No me importa cómo esté escrito: grep -i

Una de las primeras dificultades que podemos encontrar, es que el texto no siempre aparece exactamente como lo esperamos... o como lo recordamos.
El mismo puede estar en mayúsculas, en minúsculas, o en una combinación de ambos casos.
Por ejemplo, yo mismo, ayer, creé una función llamada "obtener_noticias_openbsd" y la estaba invocando como "obtener_noticias_OpenBSD"... Resultado: error de ejecución en el flujo esperado del programa.
Es el eterno dilema de escribir las cosas como realmente se debe, por un lado, vs lo que se recomienda en programación, por otro (sumale a eso "año vs anio", "función_principal vs funcion_principal", y así).
Acá es donde entra en juego JuanI Vellozo, quien presentó este ejemplo: el de la opción "-i". Al utilizarla, grep deja de distinguir entre mayúsculas y minúsculas (deja de lado el "case sensitive"), lo cual permite encontrar coincidencias sin la preocupación de cómo fue escrito el texto. Esta es una mejora procedimental que evita muchos "falsos negativos" cuando se están buscando palabras clave o comandos problemáticos dentro del código.

Ejemplo.

Supongamos que existe un archivo llamado "log.txt" con un contenido como este:

[001] Error al iniciar módulo: no se encuentra el archivo o directorio.
[002] OK.
[003] OK.
[004] Conexión no establecida
[005] OK.
[006] OK.
[007] ERROR: módulo de conexión faltante.
[008] Usuario no conectado.
[009] OK.
[010] OK.
[011] Saliendo con código de error 1.

Al hacer

grep -i "error" log.txt

la terminal nos devuolverá tanto "Error", como "ERROR" y "error", resolviendo el problema de las mayúsculas sin tener que "debuguear" demasiado.


Pero... ¿en dónde está el error, exactamente? grep -n

Cuando el archivo crece o se empieza a volver "inmanejable", encontrar una coincidencia ya no es suficiente: también hay que ubicarla.
Gracias a Ramiro Bergara, vimos la demostración de que la opción -n descubre este contexto que en muchas ocasiones es fundamental, mostrando el número de línea junto a cada resultado.
Esto potencia a la utilidad de búsqueda de grep, porque permite saltar directamente al lugar exacto dentro del archivo en donde está el error o lo buscado. En tareas de depuración o edición, ese número deja de ser un simple detalle, pasando a ser una guía importante.

Ejemplo.

grep -n "error" log.txt

El resultado incluirá tanto las líneas como sus números reales, algo así como:

  1:[001] Error al iniciar módulo: no se encuentra el archivo o directorio.
  7:[007] ERROR: módulo de conexión faltante.
11:[011] Saliendo con código de error 1.

Esto permite ubicar rápidamente al problema.


¿Voy a tener que hacer esto en cada uno de mis programas? grep -r

Hay un gran salto que es posible dar cuando no estamos obligados a parametrar nuestras búsquedas dentro de un solo archivo. En el caso de un programador que posee una cantidad de programas en su haber, la información, lógicamente, está distribuida en múltiples archivos y directorios. Thiago González mostró que grep puede recorrer directorios y archivos enteros de manera recursiva, buscando en todo lo que a su paso encuentra. Esto hace que la necesidad de tener que saber de antemano en dónde está lo que buscamos, sea algo totalmente irrelevante, ya que en lugar de ir abriendo todos los archivos uno por uno y aplicando herramientas de búsqueda en cada uno de ellos, se delega la totalidad de dicha tarea a este comando, el cual lo hará de manera inmediata y efectiva.

Ejemplo.

Este es un volcado real de mi directorio de scripts local, el cual busca la ocurrencia "set -e" en "$PWD", s decir "en el lugar en donde esté 'parada' la terminal en ese momento".

grep -r "set -e" $PWD

/mnt/HDD_4TB/datos_linux/01_Entropía/CodeBerg/_GeneBerg/_respaldos/geneberg.sh:set -euo pipefail
/mnt/HDD_4TB/datos_linux/01_Entropía/CodeBerg/_GeneBerg/geneberg.sh:set -euo pipefail
/mnt/HDD_4TB/datos_linux/01_Entropía/CodeBerg/KDEnTux/KDEnTux.sh:set -e # Detención script inmediatamente si algún comando falla.
/mnt/HDD_4TB/datos_linux/01_Entropía/CodeBerg/KDEnTux/KDEnTux.sh:    # Se utiliza "vainfo" para listar puntos de entrada VA-API. Si falla, KDEnTux se detendrá gracias al "set -e" del inicio.
/mnt/HDD_4TB/datos_linux/01_Entropía/CodeBerg/GeneRead/generead.sh:set -euo pipefail 
/mnt/HDD_4TB/datos_linux/01_Entropía/CodeBerg/IA_local/instalador_ia_local.sh:set -euo pipefail


Pero... yo quiero ver "todo lo otro", no "eso"... grep -v

A este atributo de grep, creo que lo charlamos entre todos, y tiene que ver con otra situación frecuente, que es la de no siempre necesitar ver lo que coincide, sino lo inverso.
Me explico mejor: a veces lo que interesa es limpiar un archivo, eliminar líneas irrelevantes o quedarse con lo que no cumple con cierta condición.
Para eso existe "-v", que invierte el criterio de búsqueda: en lugar de mostrar coincidencias, muestra todo lo demás, es decir, todo lo que NO coincide con lo que le estemos indicando.
Esto es especialmente útil al ponernos a trabajar con archivos de configuración o de registros en donde el filtrado de "ruido" es imprescindible (comentarios, líneas repetitivas, etc).

Ejemplo.

Dado un archivo de configuración con comentarios:

# Configuración del sistema
usuario=admin
# Contraseña
password_SHA-256=p989e5ap9h7t6894d4topja34l5l69xq

Podemos quitar los comentarios con:

grep -v "^#" config.conf

El resultado será solo las líneas útiles, sin las que empiezan con #:

usuario=admin
password_SHA-256=p989e5ap9h7t6894d4topja34l5l69xq


Un dato "de color": grep --color=auto

Por último, está el aspecto visual, que muchas veces se subestima. Cuando se trabaja con grandes volúmenes de texto, encontrar rápidamente coincidencias dentro de cada línea puede ser más dificultoso de lo que parece, y más cuando llevamos mirando el mismo código durante horas.
La opción --color=auto resuelve esto resaltando las coincidencias directamente en la salida. No cambia el resultado en sí, pero sí la forma en que lo percibimos, haciendo que la lectura sea más inmediata y menos propensa a errores.

Ejemplo.

Volvamos al caso del ejemplo en grep -r.
Era este: grep -r "set -e" $PWD
Pero supongamos que queremos resaltar visualmente a las ocurrencias encontradas, no solamente volcarlas en pantalla.
En ese caso, podemos simplemente intercalar la opción correspondiente en la misma línea, de esta manera:

grep --color=auto -r "set -e" $PWD

El resultado, será el mismo que el mostrado en la imagen de este artículo.

P.D.: para que no te rompas la cabeza intentándolo... Porque te estoy leyendo el pensamiento y ya sé que vas a querer hacer lo mismo que yo intenté en algún momento ("color=1", "color1", etc...), y te quiero ahorrar tiempo y enseñarte algo más...

  • "--color" no acepta colores, solo acepta "auto", "always" y "never" (el cual ya viene por omisión y no es necesario, en principio).
  • "color=auto", colorea solo si detecta que la salida va a una terminal o pantalla, pero si detecta que la salida es redirigida a un archivo, deja de resaltar con color automáticamente.
  • "color=always" se comporta de manera literal: inserta comandos de color aunque eso pueda llegar a ensuciar su salida.
Este modo se vuelve útil en casos específicos, por ejemplo cuando querés forzar colorido a través de una tubería hacia otro comando o programa que sí sepa interpretar código ANSI, el cual es, en definitiva, el código generado por grep cuando está en modo "color=always".


Epílogo.

grep posee muchas opciones, y de hecho te invito a que las investigues por tu cuenta, pero éstas, utilizadas de manera combinada (tal como nos enseña UNIX), transforman a cualquier comando (en este caso, a grep) en algo más que una simple orden o un simple buscador de texto: permiten explorar archivos, localizar problemas y filtrar información con precisión. 
Esta guía fue escrita para mis estudiantes y para los lectores que la aprovechen, pero también para mí mismo, porque al bajar a tierra escribiendo lo que uno aprendió, lo "hace carne".
Para alguien que esté empezando a utilizar este comando, la moraleja es que no es tan importante tratar de memorizar todas las posibilidades como entender que cada una de estas variantes responde a una necesidad concreta que irá apareciendo naturalmente al trabajar con datos reales en BASH.


¿Cómo ejecutar con "sudo" cuando el usuario "is not in the sudoers file".

Hoy tuve que hacer un malabar en un sistema Mageia de la UTU que yo mismo administro.
Los sistemas Linux que pasan por mí, son endurecidos a un nivel bastante paranoico, y una de las primeras cosas que hago, es quitar a los usuarios del grupo "wheel" para que no puedan hacer "sudo"; o sos root, o no sos root: nada de filosofía Linux, acá lo que corre es filosofía UNIX.
Lo que esto significa, es que si no sabés la contraseña de root y hacés sudo, no podrás seguir adelante porque el sistema, lo que te pedirá, será tu contraseña (un contrasentido total heredado del mundo de fantasía en el que está viviendo Linux desde hace muchos años) y no la de root.
Observá los 2 ejemplos en las siguientes 2 imágenes. ¿Te ha sucedido algo así?


Pues bien, hay veces en las cuales hacer "su" y registrarse como root en la terminal (aunque poseas la contraseña de root) no es suficiente, ya que la ejecución de un programa o script puede necesitar "los privilegios de sudo pero en el contexto del usuario que inició sesión en el sistema". Por ejemplo, si el usuario es "estudiante" y el script tiene que correr para "estudiante", no podés hacer "su" en la terminal y "pasarte a sudo completamente", porque el contexto del usuario "estudiante" se perdería.
Tampoco podés hacer "sudo ALGO" siendo usuario "estudiante sin wheel" porque te pasaría lo que se muestra en las imágenes de arriba.

Pues, en Linux hay solución para casi todo, y esta no es la excepción.

Podés agregar a cualquier usuario al grupo wheel, o al archivo de sudoers.
Pero esto rompería la filosofía UNIX en donde "root es root" y "user es user"

Podés "pasarte a root", como dijimos antes, pero eso rompería el contexto del usuario que realmente necesita correr el script "para él y no para root".

Entonces... parecería que no hay solución... ¿o sí?

Estarás pensando... "Páh... Soy yo el administrador; soy yo el que prohíbe hacer "sudo". En mis equipos, si no sabés la contraseña root, no podés elevar privilegios usando tu contraseña... Tiene que haber manera. Soy el "admin", sé la contraseña de root, solo debo hacer que el sistema lo entienda sin reconfigurar nada, haciendo algo al vuelo... 

Esto es posible. La "línea salvadora" es esta:

su -c "SUDO_USER=<NOMBRE_USUARIO> bash /ruta_al_script" root

Esto no solamente soluciona el problema, sino que también ejecuta al script como root, pero con SUDO_USER configurado para el usuario real, procedimiento que será utilizado por el script para saber a quién pertenece el entorno: solo tenés que sustituir <NOMBRE_USUARIO> por el nombre del usuario real.

Ejemplo con el usuario "estudiante":
su -c "SUDO_USER=estudiante bash /ruta_al_script" root

Dominando la creación de archivos con "Here-Documents" (here-docs) en BASH


Dominando la creación de archivos con "Here-Docs" en BASH.

En el desarrollo de scripts, a menudo necesitaremos crear archivos de configuración XML, JSON, o bien scripts auxiliares que contendrán múltiples líneas de texto. Lo básico es escribir un "echo" tras otro, completando toda la secuencia.
Pero existe un método que creo que es mucho más elegante y bonito, el cual consiste en utilizar un "Here-Document" (o "Here-Doc").

Automatizando la configuración: el poder de "sed".

Imaginemos que necesitamos insertar una configuración específica en el archivo de acciones de Thunar (uca.xml), y que en lugar de escribir el archivo manualmente, utilizamos este bloque de código basado en el comando sed:

sed -i "/<\/actions>/i\
<action>\\
    <icon>terminal</icon>\\
    <name>ThunExec</name>\\
    <command>$terminal_predef</command>\\
    <description>Ejecuta en terminal preferida</description>\\
    <patterns>*.sh;*.bash;*.zsh;*.fish</patterns>\\
    <appears-on-files>true</appears-on-files>\\
</action>" "$thun_uca"


¿Qué hace este bloque?

Es un "inyector" de código. Busca la etiqueta de cierre </actions> dentro del archivo, y justo antes de ella (i), inserta todo el bloque <action>...</action> que configuramos. Es una forma quirúrgica de añadir funciones a un archivo de configuraciones, sin borrar lo que allí ya existía.

  • La primera "i" (sed -i...) es una opción del comando sed que significa "in-place", la cual le dice al comando: "no me muestres el resultado por pantalla, editá directamente el archivo original". Si no pusieses esta "i", sed solo imprimiría los cambios en la terminal y el archivo no se modificaría.

  • La segunda i (la del medio), es el comando de inserción "insert". En la sintaxis de sed, cuando ponés una barra "/busqueda/i", le estás diciendo al comando: "en la línea en donde encuentres esta búsqueda, insertá lo que siga a continuación, pero justo antes de esa línea".


El desafío: ¿cómo crear el archivo inicial?

Para que el comando "sed" anterior funcione, el archivo "$thun_uca" debe existir previamente y contener al menos las etiquetas básicas. Para lograr esto, tenemos dos caminos.

1. La "millonada de echos vomitantes". 

Es la opción que utilizan muchos programadores. Es funcional, pero un poco más difícil de mantener, además de ser menos elegante:

if [[ ! -f "$thun_uca" ]];then
    echo '<?xml version="1.0" encoding="UTF-8"?>' > "$thun_uca"
    echo '<actions>' >> "$thun_uca"
    echo '</actions>' >> "$thun_uca"
fi


Aquí solo hay 3 "echos", pero... ¿podés imaginar 30 o 40 de ellos?
El problema aquí es que cada línea nueva requiere un comando echo y una redirección, lo que convierte un bloque simple en una sucesión de instrucciones que  redundan sobre la misma estructura que se repite una y otra vez. Si usáramos el método tradicional, el script se volvería una tarea potencialmente problemática, ya que habría que copiar/pegar líneas "como quien lava y no escurre" o estar repitiendo código de manera enfermiza, como la máquina que NO somos.

2. La forma más elegante: los "Here-Doc"

Esta es la técnica de la que habla este artículo. Es la forma más limpia, porque nos permite definir el "molde" del archivo de una sola vez, manteniendo la estructura XML intacta y legible. Un "Here-Doc" es una forma de decirle a BASH: "tomá todo lo que se escriba a continuación como una única unidad de texto y envialo todo junto al destino". Algo así como el Hypertransport de AMD (enviar más, de un solo golpe) frente al Hyper-Threading de Intel (enviar menos, de a "golpecitos").

if [[ ! -f "$thun_uca" ]];then
cat > "$thun_uca" << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<actions>
</actions>
EOF
fi


Aquí, el bloque <actions></actions> actúa como el contenedor necesario. Una vez que este bloque crea el archivo base, el comando sed que vimos antes entrará en juego para insertar la acción "ThunExec" justo en medio de esas dos etiquetas.

¿Cómo interpretar este código?

cat > "$thun_uca": El comando cat toma lo que recibe y lo escribe en el archivo indicado por la variable $thun_uca. El símbolo > asegura que, si el archivo existe, se sobrescriba.

<< 'EOF': acá ocurre la magia. Las llaves << inician el Here-Doc. La palabra EOF es simplemente un marcador que elegimos nosotros (podría ser cualquier palabra, por ejemplo "POCHO", pero EOF —End Of File— es el estándar).

Importante: al envolver EOF en comillas simples ('EOF'), le estamos dando una instrucción vital al shell: "no interpretes nada de lo que hay adentro, sé literal". Esto evita que BASH busque variables con $ para expandirlas o intente ejecutar comandos dentro del texto, en lugar de tratar a todo como texto plano.

El final del bloque: el EOF que aparece al final, solo y sin sangrías, le avisa a BASH: "hasta acá llegó el archivo".

Reglas de oro para estudiantes.

El delimitador final debe estar solo: nunca pongas espacios o tabulaciones antes del EOF de cierre, porque si lo hacés, BASH no reconocerá el fin del bloque y el script se quedará "colgado" esperando el cierre.

Literalidad: gracias a las comillas simples ('EOF'), podés copiar y pegar cualquier fragmento de código (HTML, XML, JSON, Python) dentro del bloque sin miedo a que los caracteres especiales (como $ o ") rompan el flujo de tu script.

Orden: esta técnica es la forma más "limpia" de gestionar configuraciones. Mantiene el contenido del archivo de destino visualmente idéntico a cómo debería quedar en el medio de almacenamiento, facilitando mucho la edición futura.

Nota importante sobre la sangría (indentación, tabulación) dentro del "Here-Doc".

Indentar, tabular, sangrar el texto al programar es "mandatory!", al igual que comentar lo no obvio.
Es posible que al escribir tu código dentro del Here-Doc quieras usar tabulaciones o espacios para que el XML se vea ordenado. Podés hacerlo sin problemas, pero con una advertencia: el delimitador de cierre (el EOF, el POCHO) debe estar pegado contra el margen izquierdo de la pantalla. Si ponés espacios antes del EOF final, BASH pensará que esos espacios son parte del contenido que debe buscar, no los encontrará, y tu script se quedará "colgado" esperando el cierre.

El truco avanzado: si necesitás que el código dentro del bloque también tenga sangría visual y que el EOF final pueda estar alineado con ella, podés usar <<-EOF (agregando un guión después de los signos "menor que"). Ese mismo guión será el que le indique a BASH que ignore todas las tabulaciones iniciales de cada línea.

Así es cómo quedaría el código, aplicando el truco del guión:

if [[ ! -f "$thun_uca" ]];then
    cat > "$thun_uca" <<- 'EOF'
        <?xml version="1.0" encoding="UTF-8"?>
        <actions>
        </actions>
    EOF
fi


Como podés ver, tanto el bloque interior como el EOF de cierre pueden estar perfectamente indentados, y BASH, gracias a ese guión, ignorará esas tabulaciones iniciales al procesar el archivo. Esto hace que el código quede en consonancia con los "case", "if", etc, que ya poseas en tu script.

NOTA EXTREMADAMENTE IMPORTANTE: para que esto funcione, la sangría dentro del bloque debe hacerse con tabulaciones reales ([Tab]) y no con espacios ([Space]), ya que <<- está diseñado específicamente para ignorar caracteres de tabulación, no "espacios puestos con la barra espaciadora", al inicio de cada línea incluida en el bloque.

De la estructura clásica a la potencia del "cortocircuito" en BASH


De la estructura clásica a la potencia del "cortocircuito" en BASH.


En BASH, existen muchas formas de tomar decisiones.
En este artículo, vamos a hacer un breve "viaje" desde la estructura más básica del "if" hasta una técnica avanzada y compacta que verás en los scripts que más experiencia acumulada encierran: el operador de "cortocircuito".

1. Punto de partida: el "if" básico.


Todo estudiante comienza por aquí. Es la forma más legible y segura de ejecutar algo si se necesita verificar el cumplimiento de una condición.

# Si el archivo existe, notificarlo.
if [[ -f "$archivo" ]];then
    echo "El archivo existe."
fi


2. Agregando alternativas: "else" y "elif".

En cuanto el script comienza a crecer, es necesario empezar a manejar el "qué pasa si no", y aquí es en donde entran en escena los actores "else" (si no) y "elif" (y si).

if [[ -f "$archivo" ]];then
    echo "Es un archivo regular."
elif [[ -d "$archivo" ]];then
    echo "Es un directorio."
else
    echo "No se encontró nada con ese nombre."
fi


3. El salto al minimalismo: operadores && y { }

A veces, podemos juzgar que un bloque "if" de 5 líneas para una tarea muy pequeña está ocupando "demasiado espacio visual", y es este tipo de situación el origen del código compacto, utilizando, entre otras herramientas, al operador "&&" (AND).

En BASH, el "&&" le dice al sistema: "ejecutá lo que sigue SOLO SI la operación anterior terminó con éxito".

Si solo querés ejecutar un comando, la cuestión es simple:

[[ -f "$archivo" ]] && echo "Existe."


¿Te vas dando cuenta de cómo funciona esto?

Ahora... ¿qué pasa si querés ejecutar varios comandos en una sola línea?
Para esto mismo es que están las llaves "{}", las cuales se pueden utilizar en combinación con "&&" (AND - "si esto es cierto, hacé lo siguiente") y "||" (OR - "si lo anterior falló, hacé esto").

[[ -f "$archivo" ]] && { echo "Es un archivo regular."; exit; }
[[ -d "$archivo" ]] && { echo "Es un directorio."; exit; }
echo "No se encontró nada con ese nombre."


Este código es equivalente al "if" completo (if/else/elif/fi) de más arriba
Son 3 líneas en comparación con 7: menos de la mitad,

Y podemos llevarlo al extremo "oneliner", que es una técnica que yo usaba mucho cuando programaba en BASIC, hace muchos años atrás:

[[ -f "$archivo" ]] && { echo "Es un archivo regular."; exit; };[[ -d "$archivo" ]] && { echo "Es un directorio."; exit; };echo "No se encontró nada con ese nombre."

Una sola línea. ¿Qué me contás?

Reglas de oro para usar las llaves.

  • Espacios obligatorios: siempre debe haber un espacio después de { y antes de }
  • El punto y coma final: el último comando dentro de las llaves debe terminar en punto y coma antes de cerrar la llave, para que BASH sepa que el bloque terminó. Esto no es como lo grotesco de Java, al que hay que estar avisándole en cada línea que la línea se terminó, poniendo SIEMPRE ";". Esto en BASH significa "se terminó la línea", pero NO ES OBLIGATORIO, y de hecho, se usa extremadamente poco.


¿Cuándo utilizar cada estilo?

Debes utilizar el "if/elif/else/fi" tradicional cuando se trate de una lógica compleja o estés escribiendo un script que otros (o vos mismo en el futuro) necesiten leer con total claridad y sin andar interpretando "código barroco".

Te recomiendo que, si vas a utilizar este método de "&&", "||" y llaves "{ ...; }", lo hagas ante una validación rápida y corta. Ahorra mucho espacio y, una vez que te acostumbrás a leerlo, hace que tu código se vea mucho más dinámico y fluido.

Simplificando tu código BASH: de bloques "if" a soluciones minimalistas.


Simplificando tu código BASH: de bloques "if" a soluciones minimalistas.


Cuando estamos aprendiendo a programar en "shell", tendemos a usar estructuras largas para tareas simples. 
Vamos a ver cómo transformar un bloque de código común en una solución que si hablamos de programas de código muy extenso, puede llegar a ser mucho más profesional, y también de cómo gestionar archivos de configuración de forma más "limpia".

El desafío de las variables vacías.

Imaginemos que nuestro script necesita saber el nombre del usuario. Si por alguna razón no logra saberlo, queremos que guarde un mensaje "por omisión". Normalmente, escribiríamos algo así, lo cual estaría muy bien:

if [[ -z "$usuario" ]];then
    usuario="Desconocido"
fi


Esto funcionará, pero BASH tiene un operador de expansión conocido como "parámetro por defecto" que hace exactamente lo mismo en una sola línea, llenando él mismo el contenido de la variable sin tener que dar tanta vuelta nosotros a nivel código, y sin pedirle a él que de tanta vuelta interna:

usuario="${usuario:-Desconocido}"


¿Cómo se interpreta esto?

Las llaves "${ }" le dicen a BASH que preste atención al estado de la variable.
El símbolo ":-" actúa como una especie de "plan B" en caso de que la variable "usuario", por algún motivo, esté vacía o no haya sido inicializada, y entonces poder utilizar el texto que sigue.
Si ya tiene un valor, no toca nada. Es ideal para configurar valores iniciales de manera automatizada, sin tener que "llenar" el script de condiciones o igualaciones.
Va otro ejemplo, para terminar de redondear el tema.

Supongamos que tu script permite elegir un color de fondo, pero que si el usuario no elige ninguno, el script tenga que utilizar uno obligatoriamente.

La forma más típica:

if [[ -z "$col_fondo" ]];then
    col_fondo="azul"
fi


La forma que estamos estudiando en este artículo:

col_fondo="${col_fondo:-azul}"

En este caso, el "plan B" asegura que el script siempre tenga un color para referenciarse y no fallar, sin importar si el usuario lo omitió deliberadamente o se olvidó de configurarlo con anterioridad a la ejecución de dicha línea.

Flag Counter Visitas previas a la existencia de este contador: 3433

Artículos aleatorios

    Páginas: