1

I know this is almost too complicated for scripting purposes, but bear with me.

I know how you can declare arrays:

arr=(hello world)
echo ${arr[1]} # "world"

And I know that you can use hash maps in bash:

declare -A map=([hello]=world [foo]=bar)
echo ${map[hello]} # "world"

But can you have hash maps that have arrays as values in bash? I've tried several syntaxes, but usually I got a hash map, which had whitespace seperated list of string as the value associated with the hash

EDIT:

An example: I want to write an adapter toolNew for a cmdline tool toolOld. Both just printout some information about the system.

toolOld can take nine different arguments a1, a2, a3, b1, ..., or c3, which I want to simplify.

I.e. toolNew only takes three differen arguments a, b, or c.

The (imo) cleanest way to do this would be to have a function

toolNew() {
    newArgument="$1"
    for argument in "${argumentMap[newArgument][@]}"; do
        toolOld "$argument"
    done
}
hgiesel
  • 5,430
  • 2
  • 29
  • 56
  • Can you give an example of what you mean? – 123 Aug 25 '17 at 13:08
  • 4
    No. Arrays are not first-class values in `bash`. Instead, the shell provides array-like syntax that basically disguises the uses of similarly named variables. `ksh` does allows nested arrays, but if you need this type of rich data structure, something other than shell is a much better choice. – chepner Aug 25 '17 at 13:13
  • Bash does not support multidimensional arrays (hashes being considered 'associative arrays'). – blackghost Aug 25 '17 at 13:15
  • You may want to check out https://stackoverflow.com/a/6151190/7673414 for a method of faking things though (basically make your keys something like `hello,1`, `hello,2`, and then generate a key based on the original hash key and index you're looking for. – blackghost Aug 25 '17 at 13:20
  • Instead of actually storing arrays, you could store their *names* in the map and use `eval` to retrieve their values. It's terribly unsafe but possible. – Socowi Aug 25 '17 at 13:34

1 Answers1

0

If you are using a recent enough version of bash you could emulate this with functions:

  1. Create array variables which name could be, e.g., the concatenation of your map keys and values (helloworld, foobar...).
  2. Use variable references (declare -n) to reference them.

Example:

declare -A map=([hello]=world [foo]=bar)

function set_entry ()
{
    local key="$1"
    local val="${map[$1]}"
    declare -n entry="${key}${val}"
    entry[$2]=$3
}

get_entry ()
{
    local key="$1"
    local val="${map[$1]}"
    declare -n entry="${key}${val}"
    echo "${key}${val}[$2]=${entry[$2]}"
}

declare -a helloworld=( 0 1 2 )
declare -a foobar=( 3 4 5 )

And then:

$ get_entry hello 1
helloworld[1]=1
$ get_entry foo 0
foobar[0]=3
$ set_entry foo 0 7
$ get_entry foo 0
foobar[0]=7
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51