Los diccionarios Bash le brindan mapas hash y matrices asociativas en scripts de shell de Linux. Le mostraremos cómo usar estas poderosas y útiles estructuras de datos en sus propios scripts de shell de Linux.
Una rosa con cualquier otro nombre
El nombre formal de los diccionarios es matrices asociativas. Además se denominan tablas hash y mapas hash. Son una estructura de datos que funciona de manera semejante a una matriz regular, pero con una diferencia significativa.
Una matriz es una colección de valores de datos que se encuentran en una estructura de datos. Para tener acceso a cualquiera de los valores de datos, que se conocen como ítems de matriz, debe conocer su posición en la matriz. La posición de un elemento de la matriz en la matriz se conoce como su índice, por lo que estos tipos de matrices se conocen como matrices indexadas. Son el tipo de matrices más usado.
A pesar de esto, disponen un inconveniente. ¿Cómo accede a un elemento de matriz si desconoce su posición dentro de la lista? Debe ejecutar todos los ítems de la matriz, probando para ver si el valor en esa ubicación es el que está buscando.
Las matrices asociativas superan ese problema. No usan números enteros para identificar de forma única los ítems de la matriz. Usan palabras únicas reconocidas como palabras clave. Puede recuperar el valor de un elemento de matriz usando su keyword, sin tener en cuenta dónde se encuentre dentro de la matriz. Con una matriz indexada, los números enteros que representan las posiciones dentro de la matriz están en orden ascendente. Las palabras clave en una matriz asociativa pueden estar en cualquier orden.
Puede buscar un valor en una matriz asociativa buscando con su keyword. Buscar una palabra y recuperar su valor asociado simula buscar una palabra en un diccionario y hallar su significado. Es es por esto que que las matrices asociativas se conocen como diccionarios.
Bash 4.0 o superior
Las matrices asociativas son compatibles con la versión 4.0 o superior del shell Bash. Si está usando una distribución de Linux actual, debería estar bien. Para verificar su versión de Bash, use este comando:
bash --version
La máquina utilizada para investigar este post tiene instalado Bash 5.1.4, por lo tanto estamos listos para comenzar.
Principios básicos
Para crear una matriz asociativa en la línea de comandos de la terminal o en un script, usamos el comando Bash declare. los -A
La opción (asociativa) le dice a Bash que esta será una matriz asociativa y no una matriz indexada.
declare -A acronyms
Esto crea una matriz asociativa llamada «acrónimos».
Para poner algunos datos en nuestra matriz, necesitamos proporcionar palabras clave y valores. Podemos hacer esto usando este formato:
array-name[key]=Value
Agreguemos algunos ítems de la matriz:
acronyms[ACK]=Acknowledgement
acronyms[BGP]="Border Gateway Protocol"
acronyms[CIDR]="Classless Inter-Domain Routing"
acronyms[DHCP]="Dynamic Host Configuration Protocol"
acronyms[EOF]="End of Frame"
Esos comandos definen cinco ítems de matriz. Tenga en cuenta que los valores están entre comillas si hay espacios en el valor. Nuestras palabras clave se ingresaron en orden alfabético, pero se pueden ingresar en el orden que desee. Las palabras clave deben ser únicas. Si intenta crear dos entradas con la misma keyword, el segundo valor que ingrese sobrescribirá al primero. Seguirá teniendo solo una entrada con esa keyword y se asociará con el segundo valor que agregó.
Para recuperar valores de la matriz, usamos comandos en este formato:
${array-name[key]}
Podemos utilizar echo para enviar la salida a la ventana de la terminal:
echo ${acronyms[ACK]}
echo ${acronyms[DHCP]}
Utilizar bucles
Las matrices se prestan muy bien a ser utilizadas en bucles. Las matrices asociativas no son una excepción. Los bucles proporcionan formas eficientes de invocar una secuencia de acciones sin secciones repetitivas de código. Antes de ver los bucles, existe una forma eficaz de declarar matrices.
Creamos las matrices usando el declare
comando (el mismo -A
opción como antes), pero proporcionamos las palabras clave y los valores como una lista en la línea de comando.
declare -A countries=( [ALB]=Albania [BHR]=Bahrain [CMR]=Cameroon [DNK]=Denmark [EGY]=Egypt )
El nombre de la matriz es «países» y está conectado a la lista de valores a través de un signo igual » =
. » La lista de valores está entre paréntesis «()
«Y cada keyword está entre corchetes»[]
“. Tenga en cuenta que no hay comas que separen los valores. Si dispone de una cadena de valor que contiene espacios, deberá envolverla entre comillas.
Para hacer que una matriz asociativa devuelva una keyword en lugar del valor, agregue un signo de exclamación «!
”Delante del nombre de la matriz. El símbolo arroba «@
”Se puede usar como comodín, dicho de otra forma, todos los ítems de la matriz.
Esta for
bucle enumerará todas las palabras clave:
for key in "${!countries[@]}"; do echo $key; done
Tenga en cuenta que las palabras clave no están necesariamente enumeradas en el orden en que se crearon, pero eso no importa. Las matrices asociativas no se centran en un índice ordenado.
Además podemos usar la expansión de parámetros para enumerar todas las palabras clave. Se enumerarán en una línea, no una por línea.
echo "${!countries[@]}"
echo "${!acronyms[@]}"
Podemos incrementar nuestro for
bucle para imprimir las palabras clave y los valores al mismo tiempo.
for key in "${!acronyms[@]}"; do echo "$key - ${acronyms[$key]}"; done
Si queremos saber cuántos ítems hay en las matrices, podemos utilizar un hash “#” delante del nombre de la matriz en lugar de un signo de exclamación.
echo "${!countries[@]}"
echo "${!acronyms[@]}"
Comprobación de que existe un elemento de matriz
Si busca una keyword pero no existe tal elemento de matriz, el valor de retorno será una cadena vacía. A veces es útil tener un indicador distinto para la presencia o ausencia de un elemento de matriz.
Podemos verificar la presencia de un elemento de matriz usando el «+_
”Operador. Tenga en cuenta que viene después de la keyword, no delante del nombre de la matriz como los operadores anteriores que hemos visto.
if [ ${acronyms[EOF]+_} ]; then echo "Found"; else echo "Not found"; fi
if [ ${acronyms[FTP]+_} ]; then echo "Found"; else echo "Not found"; fi
El elemento de la matriz con la keyword «EOF» se encuentra en la matriz, pero el elemento de la matriz con la keyword «FTP» no.
Adición de ítems de matriz
Agregar nuevos ítems a una matriz asociativa es fácil. A diferencia de algunos lenguajes de programación, no necesita establecer el tamaño de su matriz cuando la declara. Puede seguir agregando nuevos ítems sin lograr un límite superior predefinido.
Para agregar un nuevo elemento a la matriz, usamos el «+=
”Operador.
countries+=( [FJI]=Fiji )
echo "$(#countries[@]}"
echo ${countries[FJI]}
El número de ítems en la matriz ahora es seis, y la búsqueda de la nueva keyword encuentra el elemento de la matriz y devuelve su valor.
Eliminación de matrices y ítems de matriz
los unset
El comando se utiliza para quitar ítems de la matriz. Si la keyword tiene espacios, envuélvala entre comillas.
unset acronyms[EOF]
if [ ${acronyms[EOF]+_} ]; then echo "Found"; else echo "Not found"; fi
Para quitar toda la matriz, use unset
con el nombre de la matriz.
unset countries
Utilizar variables con matrices
El uso de variables con matrices asociativas es sencillo. En este ejemplo, estableceremos una clave de variable en la cadena «EOF». Usaremos la variable cuando agreguemos un nuevo elemento de matriz a la matriz. En realidad, estamos reemplazando el elemento de matriz que eliminamos previamente.
Recuperamos el nuevo elemento de la matriz llamándolo con la nueva keyword y además, usando la variable. Si la keyword contiene espacios, deberá colocar el nombre de la variable entre comillas.
key=EOF
acronyms[$key]="End of Frame"
echo ${acronyms[EOF]}
echo ${acronyms[$key]}
Se creativo
Nuestros ejemplos han sido colecciones de información donde cada elemento de la matriz es independiente de todos los demás, como un diccionario. Cada uno es una definición única. Pero los arreglos asociativos pueden contener fácilmente una gama de piezas de información, todas asociadas con una cosa, como las especificaciones de diferentes piezas de hardware de computadora:
declare -A specification
specification[CPU]="Dual Core AMD Ryzen 5 3600"
specification[Speed]="3600 MHz"
specification[Kernel]="5.11.0-17-generic x86_64"
specification[Mem]="1978.5 MiB"
specification[Storage]="32 GiB"
specification[Shell]="Bash"
echo ${specification[CPU]}
Escribir de manera eficiente en un idioma significa conocer los mecanismos y estructuras que ofrece, y elegir el más adecuado para el problema que se intenta solucionar. Los arreglos asociativos le brindan una forma fácil de utilizar de almacenar datos que puede buscar por nombre, como un diccionario.