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?
1 Answer 1
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)
-
Thanks, I guess I should be looking this up in the bash manual, instead of the set man :DJakub Bochenski– Jakub Bochenski2024年09月13日 12:17:27 +00:00Commented Sep 13, 2024 at 12:17
${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.