Re: Zero-length indexed arrays

2021-12-22 Thread L A Walsh






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

2021-12-22 Thread Chet Ramey

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

2021-12-22 Thread konsolebox
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

2021-12-21 Thread Lawrence Velázquez
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

2021-12-21 Thread Greg Wooledge
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

2021-12-21 Thread Dale R. Worley
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

2021-12-16 Thread Lawrence Velázquez
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

2021-12-16 Thread Lawrence Velázquez
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

2021-12-16 Thread Dale R. Worley
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