Re: Question about associative array runtime assignment vs literal initialization
Koichi Murase <[email protected]>
| Newsgroups | gmane.comp.shells.bash.bugs |
|---|---|
| Message-ID | <CAFLRLk_tZrsH_p3ZN2iN+WU2=rBVqvKcZzX9Mo2Ky_06hNNjPA@mail.gmail.com> |
2026年1月3日(土) 8:17 Greg Wooledge <[email protected]>: > On Fri, Jan 02, 2026 at 17:24:46 -0500, Chet Ramey wrote: > > On 12/31/25 6:58 PM, Koichi Murase wrote: > > > My request is essentially to defer the > > > identification of keys and values in non-subscripted forms after shell > > > expansions (while keeping the identification between subscripted vs > > > non-subscripted forms of lexical words to be performed before shell > > > expansions). > > > > OK, you want a new feature. Yes, essentially. > > Since this is not compatible with previous > > behavior, and since bash has never behaved this way, how should this new > > feature be exposed? > > > > Should there be a shell option that changes the expansion behavior? > > Some new assignment syntax? Something else? > > We're talking about this, right? > > assoc=( "${kv[@]}" ) > > Currently, the behavior makes no sense at all (from a script writer's > point of view), so I have a hard time believing anyone's using it > intentionally. Honestly, I have the same feeling as Greg. Although Chet mentioned that the kv-pair was introduced "primarily to avoid the parsing and quoting difficulties involved in finding the end of the subscript", I'm currently unsure about how it is difficult for the current specific case for « [<key>]=<value> » in the compound list. I agree that the identification of the end of the subscript becomes an issue in a context where « [<key>]=<value> » is passed as a "string", such as « ((assoc[$key]=value)) », « declare -n nref="assoc[$key]" », and « unset "assoc[$key]" ». However, the construct « [<key>]=<value> » in the compound list can be identified at the parsing time (before the expansion of $key is performed). The identification seems unambiguous, just as the normal assignment « assoc[$key]=$value » as a simple command is unambiguous. Then, I cannot stop doubting that anyone actually uses « assoc=($key $value) » as a "better" version of « assoc=([$key]=$value) ». Users can simply continue to use the traditional form « assoc=([$key]=$value) » or « assoc=(["$key"]="$value") », and there seems to be no actual benefit to using « assoc=($key $value) », introducing compatibility issues with Bash < 5.1. Even if users intentionally use the feature, users are likely to quote the words the same as they quote the words for indexed arrays, i.e., « assoc=("$key" "$value") » instead of « assoc=($key $value) » and « assoc=(key "${values[*]}") » instead of « assoc=(key "${values[@]}") ». Writing « assoc=($key $value) », expecting that $key and $value won't be word-split, seems unlikely. As far as the user quotes the words as if they were for indexed arrays, the script is unaffected even if we change the default expansion behavior of non-subscripted forms in the compound list for associative arrays. For this reason, I believe the impact is limited. However, at the same time, we have learned in many discussions on this mailing list that, once a feature is introduced, someone might be using it. I suggest the following: 1. Change the default expansion behavior of non-subscripted forms in the compound list for associative arrays. 2. Introduce a shopt option to reproduce the expansion behavior of Bash <= 5.3 (or provide it through BASH_COMPAT=5.3). > Whether the user intended to produce an array with keys 'foo' and 'baz' > or an array with the single key '[foo]=bar' the point is neither of > these things happens. > > [...] > > On the other hand, some script writers may expect bash to scan the > first element of the list to see whether it matches the form [x]=y > and if so, parse it as a key/value pair. In that case, they may also > expect every element to be scanned that way, or they may expect the > first element's format to indicate the type of parsing that's used for > all elements. > > I don't have a good idea for how to reconcile those two (or three) > expectations. Perhaps Koichi Murase does. I believe « assoc=('[2]=value1' '[4]=value2') » should cause « assoc=(['[2]=value1']='[4]=value2')» (instead of « assoc=([2]=value1 [4]=value2) ») to be consistent with the behavior of indexed arrays. In fact, the assignment « indexed=('[2]=value1' '[4]=value2') » for an indexed array doesn't try to parse "an assignment-like string inside values", even though the indexed arrays accept the index-value pairs in the compound list as « indexed=([2]=value1 [4]=value2) ». This is the same as « $(echo 'var=value1') » doesn't try to assign a value `value1' to a variable `var' but tries to execute a command named `var=value1'. The assignment forms of constructs have always been identified during parsing time, but not after expansions (except for the case where parsing happens again after expansions such as « let "assoc[$key]=1" »). Shell beginners might expect « indexed=('[2]=value')» to cause « indexed=([2]=value) » and « $(echo 'var=value1') » to cause « var=value1 », but we cannot be consistent with such a naive expectation by beginners. -- Koichi