Come eseguire l'iterazione su array associativi in ​​Bash


351

Basato su un array associativo in uno script Bash, ho bisogno di iterare su di esso per ottenere la chiave e il valore.

#!/bin/bash

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

In realtà non capisco come ottenere la chiave mentre utilizzo un ciclo for-in.


14
$ declare -A array = ([foo] = bar [bar] = foo) # Inizializza tutto in una volta
anisbet

3
Per un piccolo elenco di valori chiave potresti considerare questo:for i in a,b c_s,d ; do KEY=${i%,*}; VAL=${i#*,}; echo $KEY" XX "$VAL; done
matematica

Risposte:


582

Si accede alle chiavi usando un punto esclamativo :, si accede ${!array[@]}ai valori usando ${array[@]}.

Puoi scorrere le coppie chiave / valore in questo modo:

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

Nota l'uso delle virgolette attorno alla variabile fornell'istruzione (più l'uso di @invece di *). Ciò è necessario nel caso in cui qualsiasi chiave includa spazi.

La confusione nell'altra risposta deriva dal fatto che la tua domanda include "pippo" e "barra" sia per le chiavi che per i valori.


3
Questo è ora se si assegnano tutte le chiavi a un array:array=(${!hash[@]})
Michael-O

12
@ Michael-O: è necessario citare l'espansione dei parametri per proteggere le chiavi che potrebbero contenere spazi bianchi:array=("${!hash[@]}")
Pausa fino a ulteriore avviso.

@DennisWilliamson, grazie mille. Non avevo questo in testa.
Michael-O,

Come possiamo usare un numero di argomento della funzione anziché una variabile? ad es for i in "${!$1[@]}".
pkaramol,

2
@pkaramol: a partire da Bash 4.3 puoi usare namerefs. Esempio: 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. Si prega di consultare BashFAQ / 006 per alcune informazioni importanti.
In pausa fino a nuovo avviso.

42

Puoi accedere alle chiavi con ${!array[@]}:

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

Quindi, scorrere le coppie chiave / valore è semplice:

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

1
Ho avuto il "!" - Non me ne sono nemmeno accorto, non ce
n'era

8

Usa questa funzione di ordine superiore per prevenire la piramide del destino

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

esempio:

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

1
Non sono sicuro di come sia applicabile? La piramide del destino non è un problema puramente estetico e realmente applicabile solo nei linguaggi orientati agli oggetti?
Alexej Magura,

1
potresti spiegarlo? La funzione foreach è un po 'complicata. Non capisco
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
~
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.