So iterieren Sie über assoziative Arrays in Bash


351

Basierend auf einem assoziativen Array in einem Bash-Skript muss ich es durchlaufen, um den Schlüssel und den Wert zu erhalten.

#!/bin/bash

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

Ich verstehe eigentlich nicht, wie man den Schlüssel erhält, wenn man eine For-In-Schleife verwendet.


14
$ deklarieren -A Array = ([foo] = bar [bar] = foo) # Alle auf einmal initialisieren
anisbet

3
Für eine kleine Liste von Schlüsselwerten könnten Sie Folgendes berücksichtigen:for i in a,b c_s,d ; do KEY=${i%,*}; VAL=${i#*,}; echo $KEY" XX "$VAL; done
Mathe

Antworten:


582

Auf die Schlüssel wird mit einem Ausrufezeichen zugegriffen: Auf ${!array[@]}die Werte wird mit zugegriffen ${array[@]}.

Sie können die Schlüssel / Wert-Paare folgendermaßen durchlaufen:

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

Beachten Sie die Verwendung von Anführungszeichen um die Variable in der forAnweisung (plus die Verwendung von @anstelle von *). Dies ist erforderlich, wenn Schlüssel Leerzeichen enthalten.

Die Verwirrung in der anderen Antwort ergibt sich aus der Tatsache, dass Ihre Frage sowohl für die Schlüssel als auch für die Werte "foo" und "bar" enthält .


3
Dies ist jetzt, wenn alle Schlüssel einem Array zugewiesen werden:array=(${!hash[@]})
Michael-O

12
@ Michael-O: Sie müssen die Parametererweiterung array=("${!hash[@]}")
angeben

@ TennisWilliamson, vielen Dank. Ich hatte das nicht im Kopf.
Michael-O

Wie können wir eine Funktionsargumentnummer anstelle einer Variablen verwenden? zB for i in "${!$1[@]}"?
Karamol

2
@pkaramol: Ab Bash 4.3 können Sie namerefs verwenden. Beispiel : 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. Weitere wichtige Informationen finden Sie in BashFAQ / 006 .
Bis auf weiteres angehalten.

42

Sie können auf die Schlüssel zugreifen mit ${!array[@]}:

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

Das Iterieren über die Schlüssel / Wert-Paare ist dann einfach:

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

1
Ich hatte die "!" - nicht einmal bemerkt, es gab keine, sorry .. :)
pex

8

Verwenden Sie diese Funktion höherer Ordnung, um die Pyramide des Untergangs zu verhindern

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

Beispiel:

$ bar(){ echo "$1 -> $2"; }
$ declare -A foo["flap"]="three four" foo["flop"]="one two"
$ foreach foo bar
flap -> three four
flop -> one two

1
Ich bin nicht sicher, wie dies anwendbar ist? Ist die Pyramide des Untergangs nicht ein rein ästhetisches Thema und wirklich nur in objektorientierten Sprachen anwendbar?
Alexej Magura

1
Könntest du es erklären? Die foreach-Funktion ist etwas knifflig. Ich verstehe es nicht
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
~
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.