Re: Zero-length indexed arrays
On 2021/12/21 20:07, Greg Wooledge wrote: On Tue, Dec 21, 2021 at 10:48:07PM -0500, Dale R. Worley wrote: Lawrence Vel�zquez writes: Did you mean to say that ${#FOO[*]} causes an error? Because ${FOO[*]} does not, a la $*: The case that matters for me is the Bash that ships with "Oracle Linux". Which turns out to be version 4.2.46(2) from 2011, which is a lot older than I would expect. But it *does* cause an error in that verison: $ ( set -u ; FOO=() ; echo "${FOO[@]}" ) bash: FOO[@]: unbound variable I would recommend not using set -u. It's not as bad as set -e, but it's still pretty bad. It breaks what would otherwise be valid scripts, and the breakage is not always easy to predict, as you've now seen. Not using '-u' in bash is akin to not using 'strict' in perl. you can put int misspelled variables and not detect them -- and then wonder why your scripts don't work. If you adhere to always requiring a definition of a variable, then using '-u' is never a problem. But not using '-u', in a script where all variables are defined will show unintended errors. They key is to always require definitions, which is why I always rely on alias my='declare ' to shorten my declares.
Re: Zero-length indexed arrays
On 12/22/21 12:12 AM, Lawrence Velázquez wrote: a. Using ${a[@]} or ${a[*]} with an array without any assigned elements when the nounset option is enabled no longer throws an unbound variable error. https://lists.gnu.org/archive/html/bug-bash/2016-07/msg00031.html -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: Zero-length indexed arrays
On Wed, Dec 22, 2021 at 4:07 AM Greg Wooledge wrote: > I would recommend not using set -u. > Especially > when you need to support multiple bash versions, or even multiple shells. It's still useful during development stages. -- konsolebox
Re: Zero-length indexed arrays
On Tue, Dec 21, 2021, at 10:48 PM, Dale R. Worley wrote: > Lawrence Velázquez writes: >> Did you mean to say that ${#FOO[*]} causes an error? Because >> ${FOO[*]} does not, a la $*: > > The case that matters for me is the Bash that ships with "Oracle Linux". > Which turns out to be version 4.2.46(2) from 2011, which is a lot older > than I would expect. But it *does* cause an error in that verison: > > $ ( set -u ; FOO=() ; echo "${FOO[@]}" ) > bash: FOO[@]: unbound variable > $ bash -uc ': "${FOO[*]}"' > bash: FOO[*]: unbound variable > $ > >> Like ${FOO[*]}, ${FOO[@]} and $@ are exempt from ''set -u''. > > It looks like that's a change since 4.2.46. Yes, it appears to be from 4.4. https://git.savannah.gnu.org/cgit/bash.git/tree/CHANGES?id=15409324f1974d41c183904ad575da7188058c1c#n1512 This document details the changes between this version, bash-4.4-rc2, and the previous version, bash-4.4-beta2. [...] 3. New Features in Bash a. Using ${a[@]} or ${a[*]} with an array without any assigned elements when the nounset option is enabled no longer throws an unbound variable error. > Is there text in the manual page about that? I don't know. -- vq
Re: Zero-length indexed arrays
On Tue, Dec 21, 2021 at 10:48:07PM -0500, Dale R. Worley wrote: > Lawrence Velázquez writes: > > Did you mean to say that ${#FOO[*]} causes an error? Because > > ${FOO[*]} does not, a la $*: > > The case that matters for me is the Bash that ships with "Oracle Linux". > Which turns out to be version 4.2.46(2) from 2011, which is a lot older > than I would expect. But it *does* cause an error in that verison: > > $ ( set -u ; FOO=() ; echo "${FOO[@]}" ) > bash: FOO[@]: unbound variable unicorn:~$ bash-4.1 -c 'set -u; a=(); echo "${foo[@]}"' bash-4.1: foo[@]: unbound variable unicorn:~$ bash-4.2 -c 'set -u; a=(); echo "${foo[@]}"' bash-4.2: foo[@]: unbound variable unicorn:~$ bash-4.3 -c 'set -u; a=(); echo "${foo[@]}"' bash-4.3: foo[@]: unbound variable unicorn:~$ bash-4.4 -c 'set -u; a=(); echo "${foo[@]}"' unicorn:~$ I would recommend not using set -u. It's not as bad as set -e, but it's still pretty bad. It breaks what would otherwise be valid scripts, and the breakage is not always easy to predict, as you've now seen. Especially when you need to support multiple bash versions, or even multiple shells.
Re: Zero-length indexed arrays
Lawrence Velázquez writes: > Did you mean to say that ${#FOO[*]} causes an error? Because > ${FOO[*]} does not, a la $*: The case that matters for me is the Bash that ships with "Oracle Linux". Which turns out to be version 4.2.46(2) from 2011, which is a lot older than I would expect. But it *does* cause an error in that verison: $ ( set -u ; FOO=() ; echo "${FOO[@]}" ) bash: FOO[@]: unbound variable $ bash -uc ': "${FOO[*]}"' bash: FOO[*]: unbound variable $ > Like ${FOO[*]}, ${FOO[@]} and $@ are exempt from ''set -u''. It looks like that's a change since 4.2.46. Is there text in the manual page about that? Dale
Re: Zero-length indexed arrays
On Thu, Dec 16, 2021, at 11:45 PM, Lawrence Velázquez wrote: > Did you mean to say that ${#FOO[*]} causes an error? Because > ${FOO[*]} does not, à la $*: > > [...] > > Like ${FOO[*]}, ${FOO[@]} and $@ are exempt from ''set -u''. Perhaps you're using an old bash, like the one shipped with macOS? % /bin/bash --version | head -n 1 GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18) % /bin/bash -uc ': "${FOO[*]}"' /bin/bash: FOO[*]: unbound variable % /bin/bash -uc ': "${FOO[@]}"' /bin/bash: FOO[@]: unbound variable If so, there's not much anyone here can do about it. -- vq
Re: Zero-length indexed arrays
On Thu, Dec 16, 2021, at 11:01 PM, Dale R. Worley wrote: > A bit ago I was debugging a failing script at work. It turns out that > when you say > FOO=(x y z) > then the variable FOO is an array and is defined. But when you say > FOO=() > then the variable FOO is an array (because ${#FOO[*]} substitutes an > integer viz. 0) but it is *not* defined (because ${FOO[*]} generates an > error when "set -u" is in effect). Did you mean to say that ${#FOO[*]} causes an error? Because ${FOO[*]} does not, à la $*: % bash --version | head -n 1 GNU bash, version 5.1.12(1)-release (x86_64-apple-darwin18.7.0) % bash -uc ': "${FOO[*]}"' % bash -uc ': "${#FOO[*]}"' bash: line 1: FOO: unbound variable > It turns out that this can matter, if you do something like this: > > set -u# for safety > ... > if ... > then > FOO=(...) > else > FOO=() > fi > ... > FOO_PLUS=("${FOO[@]}" x y z w) I have to assume you meant something else here as well. This example never causes any errors. % cat foo.bash; echo set -u if [[ -n "${1+set}" ]]; then FOO=(a b c) else FOO=() fi FOO_PLUS=("${FOO[@]}" x y z w) declare -p FOO_PLUS % bash foo.bash declare -a FOO_PLUS=([0]="x" [1]="y" [2]="z" [3]="w") % bash foo.bash woot declare -a FOO_PLUS=([0]="a" [1]="b" [2]="c" [3]="x" [4]="y" [5]="z" [6]="w") Like ${FOO[*]}, ${FOO[@]} and $@ are exempt from ''set -u''. -- vq
Zero-length indexed arrays
A bit ago I was debugging a failing script at work. It turns out that when you say FOO=(x y z) then the variable FOO is an array and is defined. But when you say FOO=() then the variable FOO is an array (because ${#FOO[*]} substitutes an integer viz. 0) but it is *not* defined (because ${FOO[*]} generates an error when "set -u" is in effect). I really don't like this. But it is according to the manual (because FOO has no index that has a value), and no doubt there are scripts out there that depend subtly on this case. It turns out that this can matter, if you do something like this: set -u# for safety ... if ... then FOO=(...) else FOO=() fi ... FOO_PLUS=("${FOO[@]}" x y z w) Dale