什么是首选
if ! [ ... ]; then
Run Code Online (Sandbox Code Playgroud)
和
if [ ! ... ]; then
Run Code Online (Sandbox Code Playgroud)
实际上它们的结果相同,是否有首选语法?在前一种语法中,评估的 not 是 shell 内置的,而在后者中, not 是test一个,这有什么区别吗?
Sté*_*las 13
该!关键字是POSIX但不伯恩同时!得到了支持[/test从一开始的命令。
所以[ ! ... ]比! [ ... ].
否则,只要您不使用已弃用的-o和-a二元运算符,它们就应该是等效的(如果我们将某些旧test/[实现中的解析错误放在一边)。
实际上,在 Bourne shell 中,要做
if ! cmd1; then
cmd2
fi
Run Code Online (Sandbox Code Playgroud)
你必须这样做:
if cmd1; then
:
else
cmd2
fi
Run Code Online (Sandbox Code Playgroud)
(或使用cmd1 || cmd2,尽管这可能最终导致不同的退出状态)。
set -o errexit//set -e与ERR陷阱交互的条件部分的外if/fi语句,如通过@mosvy指出的,之间的另一区别[ ! ... ]与! [ ... ]是,后者将不会导致shell退出时! [ ... ]返回false和errexit选项上。
!应用于任何管道会取消效果,errexit因为 shell 认为管道的退出状态正在被用作条件。这同样适用于failing-pipeline || cmd或failing-pipeline && cmd...
虽然 with [ ! ... ],!只是传递给[命令的常规参数,最后就 shellerrexit而言,它只是一个[返回成功或失败退出状态的命令。
$ sh -ec '[ ! a = a ]; echo here'; echo "$?"
1
$ sh -ec '! [ a = a ]; echo here'; echo "$?"
here
0
Run Code Online (Sandbox Code Playgroud)
当这些命令作为条件部分的一部分运行不适用if/ while/until语句,因为在那里,errexit不适用。
这同样适用于ERRKorn-like shell的陷阱:
$ ksh -c 'trap "echo OUCH" ERR; ! [ a = a ]'
$ ksh -c 'trap "echo OUCH" ERR; [ ! a = a ]'
OUCH
Run Code Online (Sandbox Code Playgroud)
实际上,这可能不会产生影响,因为[几乎总是用作条件, whereerrexit不适用(无论是在if/ while/until语句中还是后跟&&/ ||)。
[ \xe2\x80\xa6 ]等于test \xe2\x80\xa6,所以! [ \xe2\x80\xa6 ]等于! test \xe2\x80\xa6。这意味着,您否定命令的结果test。在本例中,!是一个 shell 命令。
来自info bash,例如在 \xc2\xabpipelines\xc2\xbb 部分:
\n\n\n如果保留字‘!’ 在管道之前,退出状态是上述退出状态的逻辑非。
\n
另一方面,[ ! \xe2\x80\xa6 ]意味着test ! \xe2\x80\xa6。这意味着,您否定测试中的表达式。参见:!man test
! EXPRESSION\n EXPRESSION is false\nRun Code Online (Sandbox Code Playgroud)\n\n所以它可以有不同的含义。如果您有复杂的表达式,则否定可能仅适用于一部分。
\n\n这取决于你,你喜欢什么。
\n