Come passare un array associativo come argomento a una funzione in Bash?

Come si passa un array associativo come argomento a una funzione? È ansible in Bash?

Il seguente codice non funziona come previsto:

function iterateArray { local ADATA="${@}" # associative array for key in "${!ADATA[@]}" do echo "key - ${key}" echo "value: ${ADATA[$key]}" done } 

Passare gli array associativi a una funzione come i normali array non funziona:

 iterateArray "$A_DATA" 

o

 iterateArray "$A_DATA[@]" 

    Ho avuto esattamente lo stesso problema la scorsa settimana e ci ho pensato per un po ‘.

    Sembra che gli array associativi non possano essere serializzati o copiati. C’è una buona voce di domande frequenti su Bash per gli array associativi che li spiega in dettaglio . L’ultima sezione mi ha dato la seguente idea che funziona per me:

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

    Basato sulla soluzione di 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" 

    L’output sarà:

     doo: 456 pou: 789 mail: ab\npo 

    Aggiornamento, per rispondere pienamente alla domanda, ecco una piccola sezione dalla mia biblioteca:

    Iterazione di un array associativo per riferimento

     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 

    Questo è uno sviluppo del mio lavoro precedente, che lascerò qui sotto.

    @ffeldhaus: bella risposta, l’ho preso e l’ho eseguito:

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

    È ansible passare solo array associativi per nome.

    È meglio (più efficiente) passare anche array regolari per nome.

    yo:

      #!/bin/bash declare -A dict dict=( [ke]="va" [ys]="lu" [ye]="es" ) fun() { for i in [email protected]; do echo $i done } fun ${dict[@]} # || ${dict[key]} || ${!dict[@] || ${dict[$1]} 

    eZ

    Ecco una soluzione che ho trovato oggi usando eval echo ... per fare l’indecisione:

     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 

    Uscite su bash 4.3:

     def: 456 abc: 123 

    Dalla migliore guida di Bash di sempre:

     declare -A fullNames fullNames=( ["lhunath"]="Maarten Billemont" ["greycat"]="Greg Wooledge" ) for user in "${!fullNames[@]}" do echo "User: $user, full name: ${fullNames[$user]}." done 

    Penso che il problema nel tuo caso sia che [email protected] non è un array associativo : “@: si espande a tutte le parole di tutti i parametri posizionali. Se è quotato doppio, si espande in una lista di tutti i parametri posizionali come singole parole.”