3

I don't understand why the array expression is fine.

$ set -eu 
$ echo "${envs[*]}"
$ echo "${envs}"
bash: envs: unbound variable

How can I make bash fail also on such array expansion?

asked Sep 13, 2024 at 11:33
1
  • 1
    Bash treats ${array[*]} as POSIX says to treat $* with "set -u" enabled. An empty list does not cause an error. I’m sure this question has a duplicate somewhere. Commented Sep 13, 2024 at 12:05

1 Answer 1

4

The manual states (emphasis mine):

‘-u’
Treat unset variables and parameters other than the special parameters ‘@’ or ‘*’, or array variables subscripted with ‘@’ or ‘*\’, as an error when performing parameter expansion. An error message will be written to the standard error, and a non-interactive shell will exit.

So you can't.

The behaviour actually changed in that regard in 4.4 but setting BASH_COMPAT=4.3 or enabling the compat43 option doesn't restore the old behaviour.

Where the bash-4.3 behaviour can be considered buggy is that "${array[@]}" with nounset on also exits when the array is set to an empty list:

$ bash-4.3 -uc 'a=(); typeset -p a;echo "${a[@]}"'
declare -a a='()'
./bash: a[@]: unbound variable

Here, you could switch to one of the other shells with array support that behave differently in this instance:

$ zsh -uc 'echo "${envs[*]}"'
zsh:1: envs[*]: parameter not set
$ mksh -uc 'echo "${envs[*]}"'
E: mksh: envs[*]: parameter not set
$ yash -uc 'echo "${envs[*]}"'
yash: parameter `envs' is not set

Beware of:

$ mksh -uc 'a=(); typeset -p a; echo "${a[@]}"'
E: mksh: a[@]: parameter not set

Which behaves like bash-4.3 and before did, except in mksh, the variable is truely unset when assigned an empty list or when an array variable has had the last of its elements unset.

Note that POSIX requires "$@" and "$*" expansions not to exit when "$#" is 0 (empty list of positional parameters) which those shells honour1. That's not strictly speaking a variable (though zsh does map the list of positional parameters to the $argv variable), but those shells do consider that to be set even when that's to an empty list. With zsh:

$ zsh -c 'typeset @ \* argv'
@=( )
'*'=( )
argv=( )

1 but bash was one of the shells that used not to, one of the reasons things like ${1+"$@"} were used to work around that issue (and others in other old shells)

answered Sep 13, 2024 at 12:07
1
  • Thanks, I guess I should be looking this up in the bash manual, instead of the set man :D Commented Sep 13, 2024 at 12:17

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.