在这个BASH片段中,行开头的感叹号是什么?

时间:2018-03-16 00:01:40

标签: bash shell

我理解C-shell和BASH中的历史扩展,但我不明白为什么带有read命令的行上的感叹号正在我正在查看的某个源代码片段中使用:

#!/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"

为什么要否定read命令的返回值(我认为这是影响,而不是历史扩展)?除了内存外,是否有任何可能的错误情况?我能想到的唯一一个是EINTR,我认为这将是一个中止条件(SIGINTSIGHUP)。为什么你会引用起始heredoc标记(在这种情况下为EOT),而不是结尾标记?

这是来自一个主要的开源项目,所以我猜测作者有一些理由这样做,我无法辨别。

1 个答案:

答案 0 :(得分:9)

如果管道返回非零退出状态(基本上如果命令失败),set -e命令告诉bash退出。

!否定退出状态,但它也会抑制set -e的效果。这个想法是,如果一个命令作为一个条件的一部分被执行,你不想终止shell。如果它前面有!,那么shell实际上假定它作为条件执行(即使结果被忽略)。

引用bash手册:

  

如果失败的命令是shell的一部分,则shell不会退出   命令列表紧跟在'while'或'until'关键字之后,部分   'if'语句中的测试,是在a中执行的任何命令的一部分   '&安培;&安培;'或'||'列表除了最后的'&amp;&amp;'之后的命令或'||',   管道中的任何命令,但是最后一个,或者命令的返回   状态正在以'!'反转。

https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html

(在这种情况下,!与历史替换无关,这是正确的。)

read内置的返回码是

  

零,除非遇到文件结尾,read次超时(在这种情况下它是   大于128),发生变量赋值错误,   或者提供了无效的文件描述符作为-u。

的参数

此处的相关案例是文件结尾。使用read重定向<<EOT的输入(并使用-d ''禁用正常终止)意味着read命令将遇到文件结束,这将导致它返回非零状态。 !阻止此操作中止脚本(但该值仍分配给$SOME_VAR)。