Hi,
On 01/09/2021 14:38, Oğuz via austin-group-l at The Open Group wrote:
Consider the following:
true
a=$? b=`exit 1` b=$? >`echo /dev/null; exit 2`
echo $? $a $b
Having read the relevant sections of the standard a couple times, I
would expect the output to be `1 0 0';
I agree.
but that's not the case with
most shells. Below are what each shell I have on my computer output
for that script.
? a b
bash 2 0 1
bosh 2 0 0
dash 1 0 0
ksh 2 0 1
mksh 1 0 0
yash 2 0 0
zsh 1 2 1
Now, I wonder, what did I miss? Where does it say in the standard that
the value of parameter `?' is affected by redirections, and that its
value depends on assignments that appear earlier in the same command?
There are two problems here. The first is the value of $? during
expansion. The standard says:
If there is no command name, but the command contained a command
substitution, the command shall complete with the exit status of the
last command substitution performed. Otherwise, the command shall
complete with a zero exit status.
Some shells implement this by modifying $? as soon as a command
substitution finishes. As all command substitutions are processed in
order, the end result is that $? is based on the last command
substitution performed. However, there is nothing that allows $? to be
modified earlier, so this looks like a bug (#1) in those shells.
The second problem is the redirection. Based on the above, command
substitutions in a redirection are supposed to affect the exit status
just as any other command substitution, but the standard says:
3. Redirections shall be performed as described in Redirection.
4. Each variable assignment shall be expanded for tilde expansion,
parameter expansion, command substitution, arithmetic expansion,
and quote removal prior to assigning the value.
This means the command substitution in your redirection is supposed to
be performed prior to that in the variable assignment. Some shells do
not do this in the specified order, which looks like a bug (#2) in those
shells. This can be confirmed by running under 'set -x'.
Bug #1 leads to the output "1 2 1".
Bug #2 leads to the output "2 0 0".
Bug #1 & bug #2 combined leads to the output "2 0 1".
Cheers,
Harald van Dijk