Code:
${non_existent_variable:+whatever} && echo "it works"
Result is it works
. But why? part before && evaluates to empty string. Trying to run however: && echo test
gives an error.
I've got this by accident trying to create ternary operator replacement for bash with different results for set and unset variable. It works this way, but I'm lost why it works at all.
PARAM=$(${tested_variable:+false} && echo var_exists || echo var_empty)
According to the section 2.9.1 of the POSIX spec:
A "simple command" is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator.
The very last sentence of section 2.9.1 is the relavant one:
If there is a command name, execution shall continue as described in Command Search and Execution . 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.
So if after all expansion, redirections, etc, no command name is found, it is treated as completing successfully with an exit status of 0.
However, the grammar does not allow a null string prior to the &&
operator. The following is a syntax error:
&& echo it works
The only way to get a completely empty simple command is to have a non-empty string "evaporate" during expansion. One way of accomplishing that is with the unquoted parameter expansion that produces the empty string, which is exactly what ${non_existent_variable:+whatever}
does.
The resulting string is not important, what the &&
construct is testing is the exit code of the statement before it (i.e. $?
) and not what's echoed on screen. Because there wasn't an error in the parameter expansion (indeed, I'm not sure there could be an error) the statement continues.
In comments you asked why $(echo "") && echo test
echoes a value, and it's the same reason. The echo
statement exits 0
(i.e. true
) so the subshell exits 0
as well, and the statement continues running.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With