Reputation: 41
I have the following sample code for my shell script:
#!/bin/bash
x[1,1]=0
x[2,1]=1
echo "x[1,1]=${x[1,1]}"
echo "x[2,1]=${x[2,1]}"
for i in {1..2}; do
x[$i,1]=${i}
echo "loop$i x[$i,1]=${i}"
done
echo "x[1,1]=${x[1,1]}"
echo "x[2,1]=${x[2,1]}"
and I am expecting for x[1,1] to have the value of 1 and x[2,2] to have the value of 2.
But when I run the script the result is:
$ ./test3.sh
x[1,1]=1
x[2,1]=1
loop1 x[1,1]=1
loop2 x[2,1]=2
x[1,1]=2
x[2,1]=2
I expect x[1,1]
to retain the value of 1 but it happens to be 2 now. Is there something wrong with my script?
Upvotes: 1
Views: 1080
Reputation: 113904
Bash does not have 2-D arrays. The best you can do is emulate them with associative arrays.
Add the following line to the beginning of your script:
declare -A x
This makes x
into an associative array. When that is done, the script produces the output that you expect:
$ bash script
x[1,1]=0
x[2,1]=1
loop1 x[1,1]=1
loop2 x[2,1]=2
x[1,1]=1
x[2,1]=2
Unless declare -A
is used, a bash array is just an indexed array. Let's define y
as an indexed array:
$ y=()
Now, let's assign two values:
$ y[2,3]=1
$ y[22,3]=2
Now, let's use declare -p
to find out what the contents of the array really are:
$ declare -p y
declare -a y='([3]="2")'
As you can see, there is only y[3]
. The reason is that the index in an indexed array is subject to arithmetic expansion and, when given a list of comma-separated values, arithmetic expansion returns just the last one.
In other words, as far as bash is concerned, assignments to y[2,3]
and y[22,3]
are both just assignments to y[3]
. The second assignment overwrites the first.
We can see this directly if we echo the results of arithmetic expansion:
$ echo $((3))
3
$ echo $((2,3))
3
$ echo $((22,3))
3
When given a list of comma-separated values, arithmetic expansion returns the last one. This is true even if the comma-separated list is a long one:
$ echo $((1+2,3*4,5,6,7,8))
8
It is always the last value which is returned.
Let's examine what happens with associative arrays. Let's define z
as an associative array and assign some values to it:
$ declare -A z
$ z[1,2]=1
$ z[3,4]=2
$ z["Jim Bob"]=3
Now, let's see what was stored in z
:
$ declare -p z
declare -A z='([3,4]="2" ["Jim Bob"]="3" [1,2]="1" )'
This seems to be what you need.
Upvotes: 2