El problema básico aquí es que los desarrolladores de bash que diseñaron / implementaron matrices realmente atornillaron al chucho. Decidieron que ${array}
era solo una mano corta ${array[0]}
, lo cual fue un grave error. Especialmente cuando consideras eso${array[0]}
no tiene significado y evalúa la cadena vacía si el tipo de matriz es asociativo.
La asignación de una matriz toma la forma array=(value1 ... valueN)
donde el valor tiene la sintaxis [subscript]=string
, asignando así un valor directamente a un índice particular en la matriz. Esto hace que pueda haber dos tipos de matrices, indexadas numéricamente e indexadas hash (llamadas matrices asociativas en lenguaje bash). También lo hace para que pueda crear dispersas matrices indexadas numéricamente. Dejar la [subscript]=
parte es una abreviatura para una matriz indexada numéricamente, comenzando con el índice ordinal de 0 e incrementándose con cada nuevo valor en la instrucción de asignación.
Por lo tanto, ${array}
debe evaluar a toda la matriz, índices y todo. Debe evaluar al inverso de la declaración de asignación. Cualquier estudiante de tercer año de CS debería saber eso. En ese caso, este código funcionaría exactamente como podría esperar:
declare -A foo bar
foo=${bar}
Luego, pasar matrices por valor a funciones y asignar una matriz a otra funcionaría como lo dicta el resto de la sintaxis de shell. Pero debido a que no hicieron esto correctamente, el operador de asignación =
no funciona para las matrices, y las matrices no se pueden pasar por valor a funciones o subcapas o salida en general ( echo ${array}
) sin código para analizarlo todo.
Entonces, si se hubiera hecho bien, el siguiente ejemplo mostraría cómo la utilidad de las matrices en bash podría ser sustancialmente mejor:
simple=(first=one second=2 third=3)
echo ${simple}
El resultado resultante debe ser:
(first=one second=2 third=3)
Luego, las matrices podrían usar el operador de asignación y pasarlas por valor a las funciones e incluso a otros scripts de shell. Se almacena fácilmente mediante la salida a un archivo y se carga fácilmente desde un archivo a un script.
declare -A foo
read foo <file
Por desgracia, nos ha decepcionado un equipo de desarrollo de bash de otro modo superlativo.
Como tal, para pasar una matriz a una función, en realidad solo hay una opción, y es usar la función nameref:
function funky() {
local -n ARR
ARR=$1
echo "indexes: ${!ARR[@]}"
echo "values: ${ARR[@]}"
}
declare -A HASH
HASH=([foo]=bar [zoom]=fast)
funky HASH # notice that I'm just passing the word 'HASH' to the function
dará como resultado la siguiente salida:
indexes: foo zoom
values: bar fast
Como esto pasa por referencia, también puede asignar a la matriz en la función. Sí, la matriz a la que se hace referencia debe tener un alcance global, pero eso no debería ser un gran problema, teniendo en cuenta que se trata de scripts de shell. Para pasar una matriz indexada asociativa o dispersa por valor a una función, es necesario incluir todos los índices y los valores en la lista de argumentos (no demasiado útil si se trata de una matriz grande) como cadenas individuales como esta:
funky "${!array[*]}" "${array[*]}"
y luego escribir un montón de código dentro de la función para volver a ensamblar la matriz.