Re: Question about associative array runtime assignment vs literal initialization

Greg Wooledge <[email protected]>
Newsgroups gmane.comp.shells.bash.bugs
Message-ID <[email protected]>
On Mon, Dec 22, 2025 at 10:57:05 -0500, Zachary Santer wrote:
> On Mon, Dec 22, 2025 at 10:21 AM Greg Wooledge <[email protected]> wrote:
> >
> > The only known workaround is to abandon this approach entirely, and use
> > @K plus eval instead.
> 
> Think the OP would want the @Q parameter transformation in this case, actually.
> 
> $ declare -a array=(a 1 b 2)
> $ eval "declare -A params=( ${array[@]@Q} )"
> $ declare -p params
> declare -A params=([b]="2" [a]="1" )

I suppose it depends on where you're starting from.  If the original
source is an associative array, then you can use the @k (lower case)
expansion to convert it into a list of alternating keys and values:

    hobbit:~$ declare -p aa
    declare -A aa=([two]="2" ["two and a half"]="2.5" [three]="3" [one]="1" )

    hobbit:~$ printf '<%s> ' "${aa[@]@k}"; echo
    <two> <2> <two and a half> <2.5> <three> <3> <one> <1> 

Naively, then, one might expect to be able to take that list of keys and
values, and use it to reconstruct an associative array.  Unfortunately,
that's the part that doesn't work (see previous messages).

If you've already saved the list in an indexed array variable, then
it might make sense to use @Q on the saved list:

    hobbit:~$ kv=( "${aa[@]@k}" ); declare -p kv
    declare -a kv=([0]="two" [1]="2" [2]="two and a half" [3]="2.5" [4]="three" [5]="3" [6]="one" [7]="1")

    hobbit:~$ eval "declare -A newarray=( ${kv[@]@Q} )"; declare -p newarray
    declare -A newarray=([two]="2" ["two and a half"]="2.5" [three]="3" [one]="1" )

However, if you *haven't* already done an @k expansion on the original
array, and you want the most efficient way to serialize it for later
reconstruction, that's where @K (upper case) comes in handy:

    hobbit:~$ kvstring=${aa[*]@K}; declare -p kvstring
    declare -- kvstring="two \"2\" \"two and a half\" \"2.5\" three \"3\" one \"1\" "

    hobbit:~$ eval "declare -A newarray=( $kvstring )"; declare -p newarray
    declare -A newarray=([two]="2" ["two and a half"]="2.5" [three]="3" [one]="1" )

Having the array's contents in a string gives some flexibility that
you don't have with an indexed array, e.g. passing it through the
environment.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.