我最近偶然发现了一些似乎没有意义的事情:
echo "Hit ENTER to continue or CTRL+D to abort."
read -s -t 3 || {
case $? in
0) echo "should not occur"; ;;
1) echo "CTRL+D"; ;;
*) echo "Timeout"; ;;
esac
}
按预期工作(CTRL+D/EOF 和超时均被捕获),但是
echo "Hit ENTER to continue or CTRL+D to abort."
if ! read -s -t 3; then
case $? in
0) echo "should not occur"; ;;
1) echo "CTRL+D"; ;;
*) echo "Timeout"; ;;
esac
fi
NOT 是否按预期工作(
$?
始终为 0)。
为什么(以及如何)在执行
$?
的身体之前重置 if
?
有趣的是,倒置的结构:
echo "Hit ENTER to continue or CTRL+D to abort."
if read -s -t 3; then
:
else
case $? in
0) echo "should not occur"; ;;
1) echo "CTRL+D"; ;;
*) echo "Timeout"; ;;
esac
fi
确实按预期工作。这表明
!
可能对此负责,但我找不到任何文档来支持这一点。
Bash 版本:5.1.16
!
不会重置退出代码。它否定后面命令的退出代码并生成管道的最终退出代码。
Bash 文档的 “3.2.3 Pipelines” 节对此进行了解释(它也在
man bash
上,但没有章节编号)。
管道的格式是
[time [-p]] [!] command1 [ | or |& command2 ] ...
...
管道的退出状态是管道中最后一个命令的退出状态[...]。如果保留字
在管道之前,则退出状态是上述退出状态的逻辑非。!
!
不是 if
语句语法的一部分。 if
语句的语法是:
if list; then list; [ elif list; then list; ] ... [ else list; ] fi
命令列表是一个序列或一个或多个管道,由运算符
;
、&
、&&
或||
之一分隔。通常,单个管道用于描述 if
语句中的条件。
因为
!
是管道的一部分,所以您获得的结果也可以在不使用 if
语句的情况下进行描述:
$ echo foo
foo
$ echo $?
0
$ ! echo foo
foo
$ echo $?
1