Associative Arrays in Shell Scripts

I saw a trick for implementing associative arrays in a shell script. For example print array["apples"] could be scripted as echo $array$key where key=apples.

However, there was no mention of how to generate the keys to iterate over the array.
The only way I could think of was to store the keys in a variable delimited by spaces so I could use a for-loop to iterate over the array.

So, is there some other way to store the keys for later use?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Shells with associative arrays

Some modern shells provide associative arrays: ksh93, bash ≥4, zsh. In ksh93 and bash, if a is an associative array, then "${!a[@]}" is the array of its keys:

for k in "${!a[@]}"; do
  echo "$k -> ${a[$k]}"
done

In zsh, that syntax only works in ksh emulation mode. Otherwise you have to use zsh’s native syntax:

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

${(k)a} also works if a does not have an empty key.

In zsh, you could also loop on both keys and values at the same time:

for k v ("${(@kv)a}") echo "$k -> $v"

Shells without associative arrays

Emulating associative arrays in shells that don’t have them is a lot more work. If you need associative arrays, it’s probably time to bring in a bigger tool, such as ksh93 or Perl.

If you do need associative arrays in a mere POSIX shell, here’s a way to simulate them, when keys are restricted to contain only the characters 0-9A-Z_a-z (ASCII digits, letters and underscore). Under this assumption, keys can be used as part of variable names. The functions below act on an array identified by a naming prefix, the “stem”, which must not contain two consecutive underscores.

## ainit STEM
## Declare an empty associative array named STEM.
ainit () {
  eval "__aa__${1}=' '"
}
## akeys STEM
## List the keys in the associatve array named STEM.
akeys () {
  eval "echo "$__aa__${1}""
}
## aget STEM KEY VAR
## Set VAR to the value of KEY in the associative array named STEM.
## If KEY is not present, unset VAR.
aget () {
  eval "unset $3
        case $__aa__${1} in
          *" $2 "*) $3=$__aa__${1}__$2;;
        esac"
}
## aset STEM KEY VALUE
## Set KEY to VALUE in the associative array named STEM.
aset () {
  eval "__aa__${1}__${2}=$3
        case $__aa__${1} in
          *" $2 "*) :;;
          *) __aa__${1}="${__aa__${1}}$2 ";;
        esac"
}
## aunset STEM KEY
## Remove KEY from the associative array named STEM.
aunset () {
  eval "unset __aa__${1}__${2}
        case $__aa__${1} in
          *" $2 "*) __aa__${1}="${__aa__${1}%%* $2 } ${__aa__${1}#* $2 }";;
        esac"
}

(Warning, untested code. Error detection for syntactically invalid stems and keys is not provided.)

Method 2

I’m not sure what you mean by store, but you can iterate over the keys using the ${!array[@]} syntax:

$ typeset -A foo=([key1]=bar [key2]=baz);
$ echo "${!foo[@]}" 
key2 key1

So, to iterate:

$ for key in "${!foo[@]}"; do echo "$key : ${foo[$key]}"; done
key2 : baz
key1 : bar

I found a nice, short tutorial on this here.


As pointed out in the comments below, associative arrays were added in bash version 4. See here for a Linux journal article on the subject.

Method 3

Shells without associative arrays

It’s not that hard when keys are restricted to [0-9A-Za-z_] (numbers, letters, underscore).

The trick is instead of storing to array[$key], store to variables array_$key.

Set:

eval "array_$key='$value'"

Get:

value=`eval echo '$'array_$key`

Note: Values cannot contain ' (single quote).

Method 4

this works in bash

cert="first"
web="second"
declare -A assoc_array=(["cert"]="${cert}" ["web"]="${web}")
echo "first is" ${assoc_array[cert]}
echo "second is" ${assoc_array[web]}

OR

#loop
for i in "${assoc_array[@]}"
do
   echo "$i"
done

No need to use eval afaik


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x