How do I populate a bash associative array with command output?

I imagine this is somewhat brittle, but you can make the entire z=(...) assignment the result of a command substitution.

declare -A "$(echo z="($(echo '[first]=foo [second]=bar'))")"

Here is a traditional while loop approach to populate an associative array from a command's output:

while IFS= read -r; do
   declare -A z+="( $REPLY )"
done < <(printf '[first]=foo [second]=bar\n[third]=baz\n')

# check output
$> echo "${z[first]}, ${z[second]}, ${z[third]}"
foo, bar, baz

# or declare -p
$> declare -p z
declare -A z='([third]="baz" [second]="bar" [first]="foo" )'

EDIT: Your original attempt will also work with proper quotes:

$> unset z

$> declare -A z="( $(echo '[first]=foo [second]=bar') )"

$> declare -p z
declare -A z='([second]="bar" [first]="foo" )'

Given that this works:

declare -A z=([first]=$(echo 'foo') [second]=$(echo 'bar'))

I'm guessing that Bash needs to see the associative array initialization list before doing any substitutions. So I don't see a way to avoid eval:

eval "declare -A z=($(echo '[first]=foo [second]=bar'))"

What is a "usual reason" to avoid eval?

Tags:

Bash