I understand history expansion in C-shell and BASH, but I don't understand why the exclamation mark on the line with the read
command is being used in this snippet from some source I'm looking at:
#!/bin/bash
set -e
. "$(dirname "$0")/includes.sh"
! read -d '' SOME_VAR <<"EOT"
some ASCII art
EOT
echo -e "\033[95m$SOME_VAR\033[0m"
Why would you negate the return value of the read
command (I think that is its effect, not history expansion)? Are there any possible error conditions, besides out-of-memory? The only one I can think of would be EINTR
, which I think would be an abort condition ( SIGINT
or SIGHUP
). And why would you double-quote the starting heredoc
marker ( EOT
in this case), and not the ending marker?
It's from a major open source project, so I was guessing the author had some reason for doing this that I haven't been able to discern.
The set -e
command tells bash to exit if a pipeline returns a non-zero exit status (basically if a command fails).
The !
negates the exit status, but it also inhibits the effect of set -e
. The idea is that if a command is being executed as part of a condition, you don't want to terminate the shell. If it's preceded by !
, the shell effectively assumes that it's being executed as a condition (even if the result is ignored).
Quoting the bash manual:
The shell does not exit if the command that fails is part of the command list immediately following a 'while' or 'until' keyword, part of the test in an 'if' statement, part of any command executed in a '&&' or '||' list except the command following the final '&&' or '||', any command in a pipeline but the last, or if the command's return status is being inverted with '!'.
https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
(You're correct that the !
has nothing to do with history substitution in this context.)
The return code for the read
built-in is
zero, unless end-of-file is encountered,
read
times out (in which case it's greater than 128), a variable assignment error occurs, or an invalid file descriptor is supplied as the argument to -u.
The relevant case here is end-of-file. Redirecting the input of read
using <<EOT
(and disabling normal termination using -d ''
) means that the read
command will encounter an end-of-file, which would cause it to return a non-zero status. The !
prevents this from aborting the script (but the value is still assigned to $SOME_VAR
).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.