In zsh, I want to iterate over an associative array. I need both keys and values. But when I iterate over the associative array normally (for x in $assoc_array), I get only values.

All examples I've looked at show that, given a key, you can get its value from an associative array. My problem is getting the set of keys to begin with.

Does zsh support iterating over keys in an associative array?

  • If you have just a small list this might be an option: for i in a,b c_s,d ; do KEY=${i%,*}; VAL=${i#*,}; echo $KEY" XX "$VAL; done
    – math
    May 16, 2014 at 14:44

3 Answers 3


You can get both keys and values at once with this nifty parameter expansion:

for key val in "${(@kv)assoc_array}"; do
    echo "$key -> $val"

See Parameter Expansion Flags in the Zsh manual.

  • This is way simpler +1
    – TimSum
    Sep 12, 2017 at 5:53
  • 1
    This doesn't work when the keys or values have spaces in them
    – Max Coplan
    Sep 9, 2019 at 1:33
  • (@kv) is better (it works with quotes, too.).
    – HappyFace
    Oct 10, 2020 at 16:23
  • 1
    You should add double-quotes around the expansion so that empty values don't trip it up (e.g. an array set with declare -A assoc_array=([a]=A [b]= [c]=C) will print incorrectly)
    – Gairfowl
    Jan 21, 2021 at 12:08
  • 2
    @Gairfowl edited Jan 23, 2021 at 17:14

I continued searching after asking my question and found this answer on the Unix StackExchange:

typeset -A assoc_array
assoc_array=(k1 v1 k2 v2 k3 v3)

for k in "${(@k)assoc_array}"; do
  echo "$k -> $assoc_array[$k]"

Output is:

k1 -> v1
k2 -> v2
k3 -> v3
  • 2
    For anyone wanting to test this in a useful way, try with the builtin $options. (See man zshoptions)
    – mVChr
    Oct 29, 2016 at 9:29
  • What if the key is not an increasing number like foo, bar, etc like arr[foo]=baz?
    – Timo
    Dec 17, 2017 at 20:28
  • 2
    @Timo I don’t think you should expect any specific order in associative arrays. Nov 7, 2020 at 23:55

In addition to the following accepted answer,

for key val in "${(@kv)assoc_array}"; do
   echo "$key -> $val"

if you also want to sort the result by key in ascending order, you can do

for key in "${(@kon)assoc_array}"; do
   echo "$key -> ${(@v)assoc_array[$key]}"

I usually use latter form as it allows more manipulations in the loop like sorting, filtering, etc.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .