简体   繁体   中英

What is exclamation mark at beginning of line doing in this BASH snippet?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM