On Wed, Apr 07, 2021 at 01:46:27AM +0900, Koichi Murase wrote: > I remember there was some discussion in the bug-bash list on the > behavior of `test -v a[@]' which actually tests whether the array `a' > has at least one element.
> It cannot be replaced by `test -v a' because > `a' implies `a[0]' here. Both of those behaviors look wrong to me, but I seem to be in the minority. > But if I correctly understand it, `test -v > a[@]' can be replaced by `((${#a[@]}))'. Should any scripts relying on > `test -v a[@]' to test the array elements also be changed? I would never write a script like that, but it doesn't seem necessary to break any scripts that are using it. It's not a complete disaster that destroys your entire array when the user types '@', so I could live with it sticking around. Anyone using test -v 'a[$key]' as an attempt to determine whether a key exists may get the wrong answer when the key is * or @. And for the record, 'a[@]' still needs to be quoted. When you put all of these issues together, it's clear that associative arrays in bash have *deep* flaws, and require some workarounds to use safely. 1) The empty string cannot be used as an index, under any circumstances. 2) The indices * and @ may cause surprising behaviors in several different contexts. Both of these can be worked around by adopting the old "put an x in front of it" hack from the days of yore. Ironic, isn't it, how some things never die. 3) Expressions like a[$key] must be single-quoted in some contexts, or you get surprising behaviors. 4) Expressions like a[$key] must be backslash-protected in some other contexts, or you get surprising behaviors. Just ugh. > $ iref1=a[@]; printf '<%s>' "${!iref1}"; echo > <y><x> > $ key=@; iref2=a[$key]; printf '<%s>' "${!iref2}"; echo > <y><x> # <-- unexpected This test is flawed; the $key is expanded during the assignment to iref2. unicorn:~$ declare -A a=(['@']=x [1]=y) unicorn:~$ key=@; iref2='a[$key]'; printf '<%s>' "${!iref2}"; echo <x> That said, the fact that you can put 'a[@]' in an indirect variable and get an array expansion out of "${!x}" is completely repulsive to me. In the past, I have asked whether this is actually working as intended, and Chet's answer simply confused me, but near as I can tell, he seems to think it should continue doing this. So I won't say anything more about it.