[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: ${y@a} on an empty array y fails with 'y: unbound variable' if run w
From: |
Mark March |
Subject: |
Re: ${y@a} on an empty array y fails with 'y: unbound variable' if run with set -u |
Date: |
Tue, 26 Oct 2021 17:07:24 +0000 (UTC) |
>"An array variable is considered set if a subscript has been assigned a
>value."
My bad, I missed that. However, there is an argument to be made that ${foo@a}
and ${foo@A} transforms should be exempt from the nounset option if foo is an
unset array. An attempt to obtain the value (or something derived from the
value, such as its length) of an unset variable is clearly a bug in one's code.
But ${foo@a} and ${foo@A} expand to the _attributes_ of the variable, not its
value. It's fine to consider an array unset if it has no indexes/key, but even
though it is unset such an array still has attributes. Bailing out on an
attempt to access attributes (which clearly exist and can be obtained with
declare -p at the cost of forking a subshell) just because the variable has no
value seems counterintuitive and counter to the intended purpose of the nounset
option, which is to help the programmer catch bugs in her code.
>That was the result of a long discussion:
>
>https://lists.gnu.org/archive/html/bug-bash/2020-02/msg00050.html
It seems that in that thread you agreed to take steps towards making ${foo@a}
succeed when declare -p foo would succeed. I would argue that this should also
work under nounset, but I see how this may be a tough call since ${foo@a} is
technically a parameter expansion, although of a new kind -- to a string
derived from something other than the value of the parameter. I will just put
[[ -o unset ]] && { set +u; ... set -u; } around my [[ ${foo@a} =~ A ]] for now.
Thanks again for your explanation and context.
-Mark
On Tuesday, October 26, 2021, 07:02:59 AM PDT, Chet Ramey <chet.ramey@case.edu>
wrote:
On 10/25/21 8:24 PM, Mark March wrote:
> If -u is on and you declare a simple or associative array 'y' and set it
> empty, then ${y@a} will fail with 'unbound variable'.
It really is unset:
"An array variable is considered set if a subscript has been assigned a
value."
> I was able to repro this under 5.1.0(1)-release and 5.1.8. 5.0.17(1)-release
> does not seem to be affected.
Bash-5.1 fixed some bugs in this area.
> The code to reproduce (output lines begin with #>):
>
> echo $BASH_VERSION
> #> 5.1.0(1)-release
> set -u
> declare -a y=()
> echo ${y@a}
> #> bash: y: unbound variable
Yes, because it's unset, but see below.
> declare -p y
> #> declare -a y=()
> echo ${y[@]}
> #>
The `@' and `*' subscripts are exempted from the nounset option to parallel
the behavior of `$@' and `$*' when there are no positional parameters (the
latter is specified by POSIX).
> set +u
> echo ${y@a}
> #> a
>
> As you can see, turning off -u makes ${y@a} work correctly.
If the `nonunset' option is not enabled, there is a special case for the
`a' transform so it will print the attributes of an unset array variable.
That was the result of a long discussion:
https://lists.gnu.org/archive/html/bug-bash/2020-02/msg00050.html
> I wonder if this is a side-effect of the fix that you described in item (n)
> of the most recent change log:
>
> n. Fixed a bug that caused ${foo@a} to treat foo as an unset variable if it
> was an array without a value for subscript 0/"0" but had other set elements
This is not relevant, there are no set elements.
Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU chet@case.edu http://tiswww.cwru.edu/~chet/