Consider the following bash snippets. In them, I'm creating two associative arrays in different ways, and then printing one of the entries.
Scenario 1. Declaring and assigning in one statement. Works as expected:
make_person() { echo '([firstName]=Bob [lastName]=Black)'; }
declare -A person1=$(make_person)
echo "${person1[firstName]}"
Output:
Bob
Scenario 2. Declaring and assigning on two different lines. No output:
declare -A person2
person2=$(make_person)
echo "${person2[firstName]}"
Output:
Why does Scenario 1 succeed in printing the [firstName]
entry while Scenario 2 does not? Are both scenarios defined and expected behaviour?
Because declare
re-interprets and parses the arguments to detect (
)
in variable assignment and then do array assignments. Whereas in normal assignment var=anything
is always a normal assignment, in var=(anything)
the (
)
are detected when parsing the expression (when bash reads the line/input to execute). declare
works more like eval
, it re-evaluates the input.
What is the bash specific reason that Scenario 1 succeeds in printing the [firstName] entry, and Scenario 2 does not?
The "bash specific reason" is I guess it was programmed that way. The reason would be also to be compatible with POSIX, so that var=$(anything)
should result in a normal variable as in POSIX.
Are both scenarios defined
"Defined" is a bit too much, I do not see much in bash documentation about this specific syntax, but
and expected behaviour?
Yes, this is working as expected.
Just to follow up on KamilCuk's excellent answer. This is really a comment but for the formatting.
To see the effect of declare -A person2; person2=$(make_person)
use declare -p
$ declare -p person1 person2
declare -A person1=([lastName]="Black" [firstName]="Bob" )
declare -A person2=([0]="([firstName]=Bob [lastName]=Black)" )
To get this to "work", you need eval
$ eval "person2=$(make_person)"
$ declare -p person1 person2
declare -A person1=([lastName]="Black" [firstName]="Bob" )
declare -A person2=([lastName]="Black" [firstName]="Bob" )
But use the eval-like powers of declare
as you discovered in the first form: declare -A ary=$(cmd)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With