Associative arrays (Bash)

Uit De Vliegende Brigade
Naar navigatie springen Naar zoeken springen
  • Associative arrays are arrays where you can give elements their own name
  • You can use associative arrays to mimic multi-dimensional arrays, with emphasize on mimic
  • Associative arrays are new in Bash 4. To verify which version of Bash you have: bash --version

An associative array means, that the index doesn't have to be a number, but can be symbolic, or a key. E.g.:

declare -A j

j[fruit]=apple
j[color]=blue

Mimicing multidimensional arrays

Associative arrays aren't really multidimensional arrays, but they can mimic them:

unset j
declare -A j

j[0,0]="00"
j[0,1]="01"
j[0, 1]="0 1"

for i in "${!j[@]}"
do
   echo "Index: $i - Value: ${j[$i]}"
done

Output:

Index: 0, 1 - Value: 0 1
Index: 0,1 - Value: 01
Index: 0,0 - Value: 00

So, the entry with index [0, 1], is not the same as with index [0,1].

On the other hand: Does it actually matter? You can use variables for these indices. And I don't really need to make calculations concerning different dimensions.

Numerical index

Example:

declare -A arr
arr[0,0,0]="000"
arr[0,0,1]="001"
arr[0,1,0]="010"
arr[0,1,1]="011"
arr[1,0,0]="100"
arr[1,0,1]="101"
arr[1,1,0]="110"
arr[1,1,1]="111"

echo "${arr[0,0,0]} ${arr[0,0,1]} ${arr[0,1,0]} ${arr[0,1,1]}"
echo "${arr[1,0,0]} ${arr[1,0,1]} ${arr[1,1,0]} ${arr[1,1,1]}"

Symbolic index

A symbolic index is probably the same as an associative index: Referring to a cell through an association, not a number.

An example to rule 'm all:

unset j

declare -A j

j[fruit,one]=Mango
j[fruit,two]=Apple
j[bird,1]=Cockatail
j[bird,2]=Spottingbird
j[flower,1]=Rose
j[flower,2]=Sunflower
j[animal]=Tiger

for i in "${j[@]}"
do
   echo "Entry: $i"
done

Output:

Entry: Cockatail
Entry: Spottingbird
Entry: Rose
Entry: Sunflower
Entry: Tiger
Entry: Apple
Entry: Mango

Note:

  • The entries seem to appear in arbitrary order
  • The first two entries have two indices that are both symbolic
  • The last item only has one index. That's not a problem
  • No problem to loop over a multidimensional symbolic array like this :)

Loop through an associative onedimensional array

This works [1]:

declare -A assArray1
assArray1[fruit]=Mango
assArray1[bird]=Cockatail
assArray1[flower]=Rose
assArray1[animal]=Tiger

for i in "${assArray1[@]}"
do
	echo "	Entry: $i"
done	

Output:

	Entry: Mango
	Entry: Rose
	Entry: Tiger
	Entry: Cockatail

Loop through a multidimensional array

This works:

declare -A assArray1

assArray1[fruit,1]=Mango
assArray1[fruit,2]=Apple
assArray1[bird,1]=Cockatail
assArray1[bird,2]=Spottingbird
assArray1[flower,1]=Rose
assArray1[flower,2]=Sunflower
assArray1[animal,1]=Tiger
assArray1[animal,1]=Mouse

for i in "${assArray1[@]}"
do
	echo "	Entry: $i"
done

Output:

	Entry: Cockatail
	Entry: Spottingbird
	Entry: Rose
	Entry: Sunflower
	Entry: Mouse
	Entry: Mango
	Entry: Apple

The only problem: The entries seem to be quite random. This is also the case if I insert statement unset assArray1 at the beginning of the script.

Looping through the rows of an associate array: This one isn't as cool as the code before, because the index is given explicitly:

i=1
for ((i; i<=$number_of_sites; i++))
do
   echo "Row ${i}: ${site[$i,1]} &  ${site[$i,2]}"
done

Loop through the index of a multidimensional array

This works:

declare -A assArray1

assArray1[fruit,1]=Mango
assArray1[fruit,2]=Apple
assArray1[bird,1]=Cockatail
assArray1[bird,2]=Spottingbird
assArray1[flower,1]=Rose
assArray1[flower,2]=Sunflower
assArray1[animal,1]=Tiger
assArray1[animal,1]=Mouse

for i in "${!assArray1[@]}"
do
	echo "Index: $i"
done

With output:

Index: bird,1
Index: bird,2
Index: flower,1
Index: flower,2
Index: animal,1
Index: fruit,1
Index: fruit,2

However, this is totally not exciting: The index was explicitly specified when initialising the array. That's different when you initialise an array through e.g., i= ( 1 2 3 blub 5 ) (or whatever the exact syntax is).

Index + value

Again, not very exciting, but maybe instructive at times:

unset j
declare -A j

j[fruit,one]=Mango
j[fruit,two]=Apple
j[bird,1]=Cockatail
j[bird,2]=Spottingbird
j[flower,1]=Rose
j[flower,2]=Sunflower
j[animal]=Tiger

for i in "${!j[@]}"
do
   echo "Index: $i - Value: ${j[$i]}"
done

Output:

Index: bird,1 - Value: Cockatail
Index: bird,2 - Value: Spottingbird
Index: flower,1 - Value: Rose
Index: flower,2 - Value: Sunflower
Index: animal - Value: Tiger
Index: fruit,two - Value: Apple
Index: fruit,one - Value: Mango

Awk

And for something entirely else: I kinda moved from a spreadsheet to associative arrays. A while ago I saw on YouTube Gary Explains: EVERYONE Needs to Learn a Little Bit of AWK! - Maybe this is what I need?

Sources