Ash, Dash or Bash, Zsh handles invalid empty parameters ${var:?}
expansion error in a here-document differently.
Here is the experiment.sh
code using genuine POSIX grammar:
#!/usr/bin/env sh
empty_var=
read -r value << EOF
Expected fail here ${empty_var:?}"
EOF
printf '$?=%d\nvalue=%s\n' $? "$value"
And here is the code to run the experiment with different shells:
for sh in ash bash dash ksh zsh; do
printf 'Testing with: %s\n' "$sh"
LC_ALL=C "$sh" ./experiment.sh || :
echo
done
Obtained results:
Testing with: ash
./experiment.sh: 5: empty_var: parameter not set or null
$?=2
value=
Testing with: bash
./experiment.sh: line 5: empty_var: parameter null or not set
Testing with: dash
./experiment.sh: 5: empty_var: parameter not set or null
$?=2
value=
Testing with: ksh
./experiment.sh[5]: empty_var: parameter null
$?=1
value=
Testing with: zsh
./experiment.sh:5: empty_var: parameter not set
Bash and Zsh stops execution immediately while other shells continue the execution, just raising the return code $?
.
What explanations are there, for this behavior difference with this genuine POSIX grammar construct?
Is it documented why Bash or Zsh choose to exit the script rather than return a failure code like Ksh, Dash or Ash?
Note that within other contexts like expansion in a string, all shells exit out of the script.
The behavior discrepancy occurs only in here-documents as far as I know.
The relevant POSIX documentation seems to be in the Parameter Expansion section of the Open Group Shell Command Language document.
${parameter:?[word]}
Indicate Error if Null or Unset. If parameter is unset or null, the expansion of word (or a message indicating it is unset if word is omitted) shall be written to standard error and the shell exits with a non-zero exit status. Otherwise, the value of parameter shall be substituted. An interactive shell need not exit.
My reading of it is that non-interactive shells are required to exit immediately. I can't find anything to suggest that it should behave differently in here-documents. It looks like you've found a bug that affects multiple shells.