7

Bash doesn't natively support two-dimensional arrays, but I would like to simulate one. As a minimal working example, suppose that I have two arrays, a0 and a1:

a0=(1 2 3 4)
a1=(5 6 7 8)

I want to write a for loop that will print the third element of a0 and a1. Of course, I could do this manually with two explicit calls to echo:

echo ${a0[2]}
echo ${a1[2]}

But, I want to generalize this with a for loop. How can I do this?

I tried the following:

for i in ${a0[@]} ${a1[@]}
do
echo {$i}[2]
echo ${i[2]}
echo ${i}[2]
echo ${$i[2]}
echo ${${i}[2]}
done

But none of those attempts are successful; I get this output:

{1}[2]

1[2]
chgreen.sh: line 30: ${$i[2]}: bad substitution

Do you have any ideas?

1
  • 1
    What’s wrong with the accepted answer at the question you linked to?
    – Scott
    Nov 6 '14 at 1:22
5

You're iterating over the wrong thing. Your for saves each element of the array as $i, not the array's indices. What you want is something like

#!/usr/bin/env bash
a0=(1 2 3 4)
a1=(5 6 7 8)

for ((i=0;i<${#a0[@]};i++))
do
    echo ${a0[$i]} ${a1[$i]};
done
2
  • 1
    You seem to be missing the point of the question. “I want to write a for loop that will print the third element of a0 and a1.” The OP wants a multi-dimensional array, and he wants to be able to iterate over any index (dimension). In particular, he wants to print ${a0[2]} and ${a1[2]} in a way that would scale readily to a situation where he has a0, a1, a2, a3, a4, …
    – Scott
    Nov 6 '14 at 1:23
  • @Scott so you're thinking the OP wants to iterate over arrays? You are very likely right, that's not what I had understood at all. If so, your solution is just about perfect.
    – terdon
    Nov 6 '14 at 12:01
4

As you’ve presumably learned by now from your research, bash doesn’t support multi-dimensional arrays per se, but it does support “associative” arrays.  These are basically indexed by a string, rather than a number, so you can have, for example,

grade[John]=100
grade[Paul]=100
grade[George]=90
grade[Ringo]=80

As demonstrated (but not explained very well) in the accepted answer of the question you linked to, indices of associative arrays can contain commas, and so a common trick is to concatenate your individual indices (0-1 × 0-3) into a string, separated by commas.  While this is more cumbersome than ordinary arrays, it can be effective:

$ declare -A a              <-- Create the associative array.
$ a[0,0]=1
$ a[0,1]=2
$ a[0,2]=3
$ a[0,3]=4
$ a[1,0]=5
$ a[1,1]=6
$ a[1,2]=7
$ a[1,3]=8
$ for i in 0 1
> do
>     echo ${a[$i,2]}
> done
3                           <-- And here’s your output.
7
1

This is an odd way to do it but it might be useful in some cases. The problem is that the for loop will resolve your arrays into their elements and treat each element separately.

Therefore, deconstruct your arrays and make them again.

a0=(1 2 3 4)
a1=(5 6 7 8)
a0=${a0[@]}  # deconstruction
a1=${a1[@]}
for arr in "$a0" "$a1"; do a=( $arr ); echo ${a[2]}; done

Output

3

7

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.