¿Cómo pasar una matriz asociativa como argumento a una función en Bash?

¿Cómo se pasa una matriz asociativa como argumento para una función? ¿Es esto posible en Bash?

El código a continuación no está funcionando 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[@]" 

Tuve exactamente el mismo problema la semana pasada y pensé en ello por bastante tiempo.

Parece que las matrices asociativas no se pueden serializar ni copiar. Hay una buena entrada Bash FAQ a matrices asociativas que las explica en detalle . La última sección me dio la siguiente idea que funciona para mí:

 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)" 

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" 

El resultado será:

 doo: 456 pou: 789 mail: ab\npo 

Actualiza, para responder completamente la pregunta, aquí hay una pequeña sección de mi biblioteca:

Iterar una matriz asociativa por referencia

 shopt -s expand_aliases alias array.getbyref='e="$( declare -p ${1} )"; eval "declare -AE=${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 -AA=([one]=1 [two]=2 [three]=3) array.print A 

Esto es un desarrollo de mi trabajo anterior, que dejaré a continuación.

@ffeldhaus – buena respuesta, lo tomé y corrí con él:

 t() { e="$( declare -p $1 )" eval "declare -AE=${e#*=}" declare -p E } declare -AA='([a]="1" [b]="2" [c]="3" )' echo -n original declaration:; declare -p A echo -n running function tst: t A # Output: # original declaration:declare -AA='([a]="1" [b]="2" [c]="3" )' # running function tst:declare -AE='([a]="1" [b]="2" [c]="3" )' 

Solo puede pasar matrices asociativas por nombre.

Es mejor (más eficiente) pasar arreglos regulares por nombre también.

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

Aquí hay una solución que se me ocurrió hoy usando 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 la versión 4.3:

 def: 456 abc: 123 

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”.

    Intereting Posts