66

I want to access the array index variable while looping thru an array in my bash shell script.

myscript.sh
#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
for i in ${AR[*]}; do
  echo $i
done

The result of the above script is:

foo
bar
baz
bat

The result I seek is:

0
1
2
3

How do I alter my script to achieve this?

1
  • 9
    Also note that you basically never want "${array[*]}" instead of "${array[@]}". Using * instead of @ more or less treats it as a string instead of an array.
    – jordanm
    Apr 23, 2016 at 2:40

4 Answers 4

68

You can do this using List of array keys. From the bash man page:

${!name[@]}
${!name[*]}

List of array keys. If name is an array variable, expands to the list of array indices (keys) assigned in name. If name is not an array, expands to 0 if name is set and null otherwise. When @ is used and the expansion appears within double quotes, each key expands to a separate word.

For your example:

#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
for i in "${!AR[@]}"; do
  printf '${AR[%s]}=%s\n' "$i" "${AR[i]}"
done

This results in:

${AR[0]}=foo
${AR[1]}=bar
${AR[2]}=baz
${AR[3]}=bat

Note that this also work for non-successive indexes:

#!/bin/bash
AR=([3]='foo' [5]='bar' [25]='baz' [7]='bat')
for i in "${!AR[@]}"; do
  printf '${AR[%s]}=%s\n' "$i" "${AR[i]}"
done

This results in:

${AR[3]}=foo
${AR[5]}=bar
${AR[7]}=bat
${AR[25]}=baz
5
  • 3
    Although this answer accomplishes the desired outcome, it is unnecessarily obfuscated by the printf statement. For example: printf "$i=(${AR[i]})\n" or echo "$i=(${ARi]})" both give a little extra by showing how to get key & var but strictly speaking echo "$i" would have answered the OP. The rest is "bash fu" :)
    – dimmech
    Jul 4, 2019 at 14:05
  • Why is it not possible: a=(1 2);echo ${a[0]} # result: 1?
    – Timo
    Nov 26, 2020 at 7:47
  • @dimmech, I disagree. I think the printf example here is really useful too. It quickly helps orient a C or C++ programmer to how to use printf in bash, when one is already familiar with printf. I'm grateful to see this here. It gives me more value from this one answer. Feb 20, 2021 at 23:32
  • I really enjoyed this answer. When I first saw it I was annoyed by the extra syntax and format touches, but later after these inevitably became essential I came to appreciate the wonderfully concise exposition here.
    – Merlin
    Jun 24, 2021 at 1:39
  • @dimmech, see Why is printf better than echo?, echo should not be used for arbitrary data. Feb 4, 2022 at 12:37
19

Additional to jordanm's answer you can also do a C like loop in bash:

for ((idx=0; idx<${#array[@]}; ++idx)); do
    echo "$idx" "${array[idx]}"
done
1
  • 2
    Only if it was not a sparse array...
    – anthony
    Jun 19, 2020 at 11:38
7

Show indexes and values in same time (this script worked for me)

ARRAY=( "engineer " "CEO" "doctor" "teacher" )

for i in "${!ARRAY[@]}"
do
      echo " index---------------content"
      echo " $i                  ${ARRAY[$i]}"
done
2
  • Welcome to the site, and thank you for your contribution. Please note that your answer seems to reiterate what was already stated in the accepted answer. You may want to consider expanding it so that the difference to that answer becomes more visible; otherwise it would be best paced as a comment to that answer (once you have sufficient reputation).
    – AdminBee
    Feb 19, 2021 at 8:36
  • 1
    @AdminBee His answer is simplified version of the accepted answer, and it's very easy to understand. I find it more helpful than the accepted one for me.
    – preachers
    Feb 20 at 11:49
0

you can do something like this:

#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
length=${#AR[@]}
for (( i = 0; i < length; i++ )); do
  echo "$i"
done

output:

0
1
2
3
2

You must log in to answer this question.

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