On 12/7/25 5:34 AM, anonymous wrote:
Strangely, when using associative array, $() are not splitunset a ; declare -A a=( $( echo [A]=a echo '[B]=b' echo ['C']=c ) ) echo Nb of elements : ${#a[@]} declare -p a The output shows there is only one element in the associative array: Nb of elements : 1 declare -A a=([$'[A]=a\n[B]=b\n[C]=c']="" ) == What I expect == I expect the $() to be split also in associative array. In my example, the expected output is : Nb of elements : 3 declare -A a=([C]="c" [B]="b" [A]="a" )
Here's what happens. (The two examples are not exactly equivalent, because
you're not using `declare -a' in the first example, but it doesn't really
make a difference.) It's kind of complicated, but it's more or less
straightforward.
`declare' is a so-called `declaration utility'. This means that the
statement is expanded as if it were
declare -A a
a=(
$(
echo [A]=a
echo '[B]=b'
echo ['C']=c
)
)
and the assignment statement that's the argument to declare is expanded as
if it were a standalone assignment statement.
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 "". That's expanded in a variable
assignment context, so quote removal happens, and the key ends up being
$'[A]=a\n[B]=b\n[C]=c'
You can defer the expansion and let the declare builtin do it by adding a
layer of quoting. If you quote the rhs of the assignment statement, you
prevent it from being recognized as a compound assignment by the parser,
and it undergoes the `normal' string word expansions before the `declare'
builtin sees it.
For backwards compatiblity, declare accepts compound assignment statements
as arguments and treats them like standalone compound assignments. This
isn't how I would choose to do it today, but I did initially, and still
support it.
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.
Chet
--
``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
