1

When I have the following:

a=foo
b=baz

I can use

typeset "$a=$b"

But this fails if a references an array element:

$ a=foo[bar]
$ b=baz
$ typeset "$a=$b"
$ declare -p foo
declare -a foo=([0]="baz")

i.e. for some reason bar is treated like a variable name. Any ideas how to change this so I can have as result declare -A foo=([bar]="baz"), preferably without parsing $a?

1 Answer 1

2

You never declared foo as an associative array. Arrays and "scalars" (for want of a better word describing ordinary variables) never have to be declared, but associative arrays do.

Since you did not declare foo as an associative array, your code sets foo[0] to baz. It sets index zero because bar is being used in an arithmetic context (since it's an ordinary array assignment). Your bar variable, used as an index in an ordinary array, either has the value zero, or it is unset (does not exist).

In short, there is nothing in the statement foo[bar]=baz that says foo is an associative array. By default, it would be an ordinary array and bar would be interpreted in an arithmetic context as some integer index (its value would be evaluated to zero if that variable did not exist).

To get what you want, you will need to declare foo as an associative array.

a=foo[bar]
b=baz

declare -A foo

typeset "$a=$b"
declare -p foo

This would output

declare -A foo=([bar]="baz" )
7
  • Yes, but the underlying problem is that there's a whole set of (a,b) pairs coming from a file and I meant to treat associative arrays the same as other variables that were set this way previously.
    – TJahns
    Jul 15, 2021 at 13:36
  • 2
    @TJahns If you could describe the overall issue in your question, I could possibly say something bout that. At the moment though, all I have is "I have this ..., and it does not work, why and what to do?". Associative arrays need to be declare before assigned to.
    – Kusalananda
    Jul 15, 2021 at 13:41
  • @TJahns Note also that syntactically, there is nothing in foo[bar]=baz that says foo is an associative array and not an ordinary array.
    – Kusalananda
    Jul 15, 2021 at 13:43
  • I wrote in the original question that I'd like to not parse $a, if I need to emit declare -A ${a%[*} conditionally then obviously that requires parsing. I could have been more explicit in that $a and $b are examples but I imagined them being variables somehow clarifies the issue.
    – TJahns
    Jul 15, 2021 at 14:25
  • @TJahns what you want to do is more easily done with something like: declare -A foo; while read -r key value ; do foo["$key"]="$value"; done < file.txt; declare -p foo. You may also need to set the IFS shell variable to match the input file's format (e.g. if your input is delimited by anything other than whitespace)
    – cas
    Jul 15, 2021 at 14:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .