arrays - ¿Cómo pasar una matriz asociativa como argumento a una función en Bash?
associative-array associative (7)
¿Cómo se pasa una matriz asociativa como un argumento a una función? ¿Es esto posible en Bash?
El siguiente código no funciona como se esperaba:
function iterateArray
{
local ADATA="${@}" # associative array
for key in "${!ADATA[@]}"
do
echo "key - ${key}"
echo "value: ${ADATA[$key]}"
done
}
Pasar matrices asociativas a una función como matrices normales no funciona:
iterateArray "$A_DATA"
o
iterateArray "$A_DATA[@]"
Actualización, para responder completamente a la pregunta, aquí hay una pequeña sección de mi biblioteca:
Iterando una matriz asociativa por referencia
shopt -s expand_aliases
alias array.getbyref=''e="$( declare -p ${1} )"; eval "declare -A E=${e#*=}"''
alias array.foreach=''array.keys ${1}; for key in "${KEYS[@]}"''
function array.print {
array.getbyref
array.foreach
do
echo "$key: ${E[$key]}"
done
}
function array.keys {
array.getbyref
KEYS=(${!E[@]})
}
# Example usage:
declare -A A=([one]=1 [two]=2 [three]=3)
array.print A
Este es un desarrollo de mi trabajo anterior, que voy a dejar a continuación.
@ffeldhaus - buena respuesta, lo tomé y corrí con él:
t()
{
e="$( declare -p $1 )"
eval "declare -A E=${e#*=}"
declare -p E
}
declare -A A=''([a]="1" [b]="2" [c]="3" )''
echo -n original declaration:; declare -p A
echo -n running function tst:
t A
# Output:
# original declaration:declare -A A=''([a]="1" [b]="2" [c]="3" )''
# running function tst:declare -A E=''([a]="1" [b]="2" [c]="3" )''
Aquí hay una solución que se me ocurrió hoy con eval echo ...
para hacer la indirección:
print_assoc_array() {
local arr_keys="/${!$1[@]}" # /$ means we only substitute the $1
local arr_val="/${$1[/"/$k/"]}"
for k in $(eval echo $arr_keys); do #use eval echo to do the next substitution
printf "%s: %s/n" "$k" "$(eval echo $arr_val)"
done
}
declare -A my_arr
my_arr[abc]="123"
my_arr[def]="456"
print_assoc_array my_arr
Salidas en bash 4.3:
def: 456
abc: 123
Basado en la solución de Florian Feldhaus:
# Bash 4+ only
function printAssocArray # ( assocArrayName )
{
var=$(declare -p "$1")
eval "declare -A _arr="${var#*=}
for k in "${!_arr[@]}"; do
echo "$k: ${_arr[$k]}"
done
}
declare -A conf
conf[pou]=789
conf[mail]="ab/npo"
conf[doo]=456
printAssocArray "conf"
La salida será:
doo: 456
pou: 789
mail: ab/npo
De la mejor guía de Bash :
declare -A fullNames
fullNames=( ["lhunath"]="Maarten Billemont" ["greycat"]="Greg Wooledge" )
for user in "${!fullNames[@]}"
do
echo "User: $user, full name: ${fullNames[$user]}."
done
Creo que el problema en su caso es que $@
no es una matriz asociativa : "@: se expande a todas las palabras de todos los parámetros posicionales. Si se cita dos veces, se expande a una lista de todos los parámetros posicionales como palabras individuales".
Solo puedes pasar arrays asociativos por nombre.
Es mejor (más eficiente) pasar matrices regulares por nombre también.
Tuve exactamente el mismo problema la semana pasada y lo pensé durante bastante tiempo.
Parece que los arreglos asociativos no pueden ser serializados o copiados. Hay una buena entrada de Bash en las matrices asociativas que las explica en detalle . La última sección me dio la siguiente idea que me funciona:
function print_array {
# eval string into a new associative array
eval "declare -A func_assoc_array="${1#*=}
# proof that array was successfully created
declare -p func_assoc_array
}
# declare an associative array
declare -A assoc_array=(["key1"]="value1" ["key2"]="value2")
# show associative array definition
declare -p assoc_array
# pass associative array in string form to function
print_array "$(declare -p assoc_array)"
yo:
#!/bin/bash
declare -A dict
dict=(
[ke]="va"
[ys]="lu"
[ye]="es"
)
fun() {
for i in $@; do
echo $i
done
}
fun ${dict[@]} # || ${dict[key]} || ${!dict[@] || ${dict[$1]}
eZ