If an indexed array is set via compound assignment, its values are cleared at the start so any arithmetic expansions in the assignment that reference the array and any [ind]+= assignments are evaluated using the newly assigned values. However, when assigning associative arrays, any previously existing values are (re)used during assignment instead.
declare -ai a=([0]=1); a=([0]=0 [0]+=10); echo $a 10 declare -Ai A=([0]=1); A=([0]=0 [0]+=10); echo $A 11 declare -ai a=([0]=1); a=([0]=0 [0]=a+10); echo $a 10 declare -Ai A=([0]=1); A=([0]=0 [0]=A+10); echo $A 11 declare -Ai A=([0]=1); A=( 0 0 0 A+10); echo $A 11 Seems like we can just swap in the new hash at the start of the compound assignment process. But I'm probably missing something because there's a lot of code to handle pulling values out of a hash table not associated with the new variable that seems like it would not be necessary if we do so. --- diff --git a/arrayfunc.c b/arrayfunc.c index 1f70b9b5..a4166624 100644 --- a/arrayfunc.c +++ b/arrayfunc.c @@ -719,7 +719,11 @@ assign_compound_array_list (SHELL_VAR *var, WORD_LIST *nlist, int flags) if (a && array_p (var)) array_flush (a); else if (h && assoc_p (var)) - nhash = assoc_create (h->nbuckets); + { + nhash = assoc_create (h->nbuckets); + var_setassoc (var, nhash); + assoc_dispose (h); + } } #if ASSOC_KVPAIR_ASSIGNMENT @@ -727,12 +731,6 @@ assign_compound_array_list (SHELL_VAR *var, WORD_LIST *nlist, int flags) { iflags = flags & ~ASS_APPEND; assign_assoc_from_kvlist (var, nlist, nhash, iflags); - if (nhash && nhash != h) - { - h = assoc_cell (var); - var_setassoc (var, nhash); - assoc_dispose (h); - } return 1; /* XXX - check return value */ } #endif @@ -882,13 +880,6 @@ assign_compound_array_list (SHELL_VAR *var, WORD_LIST *nlist, int flags) free (val); } - if (assoc_p (var) && nhash && nhash != h) - { - h = assoc_cell (var); - var_setassoc (var, nhash); - assoc_dispose (h); - } - return (any_failed ? 0 : 1); }