44 votes

Comment passer un tableau associatif comme argument à une fonction en Bash ?

Comment passer un tableau associatif comme argument à une fonction ? Est-ce possible en Bash ?

Le code ci-dessous ne fonctionne pas comme prévu :

function iterateArray
{
    local ADATA="${@}"            # associative array

for key in "${!ADATA[@]}"
do
    echo "key - ${key}"
    echo "value: ${ADATA[$key]}"

done

}

Passer des tableaux associatifs à une fonction comme des tableaux normaux ne fonctionne pas :

iterateArray "$A_DATA"

ou

iterateArray "$A_DATA[@]"

49voto

Florian Feldhaus Points 786

J'ai eu exactement le même problème la semaine dernière et j'y ai pensé pendant un bon moment.

Il semble que les tableaux associatifs ne peuvent pas être sérialisés ou copiés. Il y a une bonne entrée dans la FAQ de Bash sur les tableaux associatifs. les explique en détail . La dernière section m'a donné l'idée suivante qui fonctionne pour moi :

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

36voto

Todd Lehman Points 353

Si vous utilisez Bash 4.3 ou une version plus récente, la fonction le plus propre est de passer le tableau associatif par son nom, puis d'y accéder dans votre fonction en utilisant une référence de nom avec l'option local -n . Par exemple :

function foo {
    local -n data_ref=$1
    echo ${data_ref[a]} ${data_ref[b]}
}

declare -A data
data[a]="Fred Flintstone"
data[b]="Barney Rubble"
foo data

Vous n'avez pas besoin d'utiliser le _ref c'est ce que j'ai choisi ici. Vous pouvez appeler la référence comme vous le souhaitez, tant qu'elle est différente du nom de la variable d'origine (sinon vous obtiendrez une erreur de type "référence de nom circulaire").

14voto

ling Points 177

Basé sur la solution 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 sortie sera :

doo: 456
pou: 789
mail: ab\npo

8voto

Orwellophile Points 2695

Mise à jour, pour répondre complètement à la question, voici une petite section de ma bibliothèque :

Itération d'un tableau associatif par référence

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

Il s'agit d'un développement de mon travail précédent, que je laisserai ci-dessous.

@ffeldhaus - belle réponse, je l'ai prise et je l'ai utilisée :

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

4voto

aks Points 647

Vous ne pouvez transmettre des tableaux associatifs que par leur nom.

Il est préférable (plus efficace) de passer les tableaux réguliers par leur nom également.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X