On 12/8/25 2:34 PM, Greg Wooledge wrote:
On Mon, Dec 08, 2025 at 11:57:02 -0500, Chet Ramey wrote:When you parse the compound assignment to an associative array assignment, the shell has to determine whether or not you're using subscripted array assignment or key-value pair assignment (kvpair). The first word in the list determines how the assignment treats the list. This happens before the individual words are expanded, since it determines how you expand keys, subscripts, and values.In this case, the word is $( echo [A]=a echo '[B]=b' echo ['C']=c ) which is not a subscripted assignment, so it's treated as the key in a kvpair. There's no value, so the value is "".This is unfortunate.If you single quote it, you'll just get a single element with the same key as above. If you double quote it, word expansion gives you declare -A a=(\n [A]=a\n[B]=b\n[C]=c\n) and `declare' runs that through compound array assignment. Since the first word is a subscripted assignment, that's how the assignment gets treated, and you end up with three elements.But it's parsing the expanded content as shell syntax:
Because you told it to.
hobbit:~$ kv=(one 1 'two point five' 2.5 $'\n\t \n' punc)
This is an indexed array.declare -a kv=([0]="one" [1]="1" [2]="two point five" [3]="2.5" [4]=$'\n\t \n' [5]="punc")
hobbit:~$ declare -A aa="( "${kv[@]}" )"
You have one round of word expansion here, and you don't do anything special to quote the white space. This command turns into the (unquoted) equivalent of declare -A $'aa=( one 1 two point five 2.5 \n\t \n punc )' and the spaces, newlines, and tab are just whitespace. It's as if you wrote declare -A aa=( one 1 two point five 2.5 punc )
hobbit:~$ declare -p aa declare -A aa=([punc]="" [two]="point" [one]="1" [five]="2.5" )
which is what you get.
This is even worse. There's a code injection vulnerability here:
You forced two rounds of word expansion.
hobbit:~$ kv=( x '$(date)' y 1 )
Another indexed array: declare -a kv=([0]="x" [1]="\$(date)" [2]="y" [3]="1")
hobbit:~$ declare -A aa="( "${kv[@]}" )"
You get declare -A aa=( x $(date) y 1 ) and the $(date) is the value for the kvpair, which is expanded as usual. There is no difference between what you wrote above and declare -A aa='( x $(date) y 1 )' or declare -A aa='( [x]=$(date) [y]=1 )' or declare -A aa=( x $(date) y 1 ) or declare -A aa=( [x]=$(date) [y]=1 ) You removed the part of my message where I said double quoting the rhs of the assignment statement -- which results in word expansion -- and giving declare an unquoted compound assignment as its argument, is only supported for backwards compatibility. I don't think you should use it.
As far as I know, the only safe way to serialize the keys and values of an associative array into a string value, and then reassign that string value back to its constituent associative array later, is to use the @K expansion plus eval:
OK. If you need to do that, then use that method.
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU [email protected] http://tiswww.cwru.edu/~chet/
OpenPGP_signature.asc
Description: OpenPGP digital signature
