arrays bash associative-array associative

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