Comment itérer sur des tableaux associatifs dans Bash

351

Basé sur un tableau associatif dans un script Bash, j'ai besoin d'itérer dessus pour obtenir la clé et la valeur.

#!/bin/bash

declare -A array
array[foo]=bar
array[bar]=foo

En fait, je ne comprends pas comment obtenir la clé lors de l'utilisation d'une boucle for-in.

pex
la source
14
$ declare -A array = ([foo] = bar [bar] = foo) # Initialise tout en une fois
anisbet
3
Pour une petite liste de valeurs clés, vous pouvez considérer ceci:for i in a,b c_s,d ; do KEY=${i%,*}; VAL=${i#*,}; echo $KEY" XX "$VAL; done
math

Réponses:

582

Les clés sont accessibles à l'aide d'un point d'exclamation:, ${!array[@]}les valeurs sont accessibles à l'aide de ${array[@]}.

Vous pouvez parcourir les paires clé / valeur comme ceci:

for i in "${!array[@]}"
do
  echo "key  : $i"
  echo "value: ${array[$i]}"
done

Notez l'utilisation de guillemets autour de la variable dans l' forinstruction (plus l'utilisation de @au lieu de *). Cela est nécessaire dans le cas où des clés contiennent des espaces.

La confusion dans l'autre réponse vient du fait que votre question comprend "foo" et "bar" pour les clés et les valeurs.

En pause jusqu'à nouvel ordre.
la source
3
C'est maintenant si vous affectez toutes les clés à un tableau:array=(${!hash[@]})
Michael-O
12
@ Michael-O: Vous devez citer l'extension des paramètres pour protéger les clés qui peuvent avoir des espaces:array=("${!hash[@]}")
Pause jusqu'à nouvel ordre.
@DennisWilliamson, merci beaucoup. Je n'avais pas cela en tête.
Michael-O
Comment utiliser un numéro d'argument de fonction au lieu d'une variable? par exemple for i in "${!$1[@]}"?
pkaramol
2
@pkaramol: A partir de Bash 4.3, vous pouvez utiliser namerefs. Exemple: declare -A aa; aa['A']=a1; aa['B']=b2; aa['C']=c3; foo () { declare -n assoc=$1; for key in "${!assoc[@]}"; do echo "Key: $key; Value: ${assoc[$key]}"; done; }; foo aa. Veuillez consulter BashFAQ / 006 pour des informations importantes.
pause jusqu'à nouvel ordre.
42

Vous pouvez accéder aux clés avec ${!array[@]}:

bash-4.0$ echo "${!array[@]}"
foo bar

Ensuite, itérer sur les paires clé / valeur est facile:

for i in "${!array[@]}"
do
  echo "key :" $i
  echo "value:" ${array[$i]}
done
tonio
la source
1
J'avais le "!" - n'a même pas remarqué, il n'y en avait pas, désolé .. :)
pex
8

Utilisez cette fonction d'ordre supérieur pour empêcher la pyramide de malheur

foreach(){ 
  arr="$(declare -p $1)" ; eval "declare -A f="${arr#*=}; 
  for i in ${!f[@]}; do $2 "$i" "${f[$i]}"; done
}

exemple:

$ bar(){ echo "$1 -> $2"; }
$ declare -A foo["flap"]="three four" foo["flop"]="one two"
$ foreach foo bar
flap -> three four
flop -> one two
coderofsalvation
la source
1
Je ne sais pas comment cela est applicable? La pyramide du destin n'est-elle pas un problème purement esthétique et ne s'applique vraiment qu'aux langages orientés objet?
Alexej Magura
1
pourriez-vous l'expliquer? La fonction foreach est un peu délicate. Je ne comprends pas.
Bálint Szigeti
-1
declare -a arr
echo "-------------------------------------"
echo "Here another example with arr numeric"
echo "-------------------------------------"
arr=( 10 200 3000 40000 500000 60 700 8000 90000 100000 )

echo -e "\n Elements in arr are:\n ${arr[0]} \n ${arr[1]} \n ${arr[2]} \n ${arr[3]} \n ${arr[4]} \n ${arr[5]} \n ${arr[6]} \n ${arr[7]} \n ${arr[8]} \n ${arr[9]}"

echo -e " \n Total elements in arr are : ${arr[*]} \n"

echo -e " \n Total lenght of arr is : ${#arr[@]} \n"

for (( i=0; i<10; i++ ))
do      echo "The value in position $i for arr is [ ${arr[i]} ]"
done

for (( j=0; j<10; j++ ))
do      echo "The length in element $j is ${#arr[j]}"
done

for z in "${!arr[@]}"
do      echo "The key ID is $z"
done
~
EJISRHA
la source