Linux 测试命令之前/之后的否定是否有区别?
我已经编写Bash脚本有一段时间了,我想知道使用Linux 测试命令之前/之后的否定是否有区别?,linux,bash,shell,unix,terminal,Linux,Bash,Shell,Unix,Terminal,我已经编写Bash脚本有一段时间了,我想知道使用test命令这两种否定形式之间是否有什么区别: if [ ! condition ]; then fi if ! [ condition ]; then fi 第一个命令告诉shell传递参数!条件进行测试,让程序自行处理否定。另一方面,第二个通过条件进行测试,并让shell本身消除错误代码 在这两种形式之间进行选择时,我应该注意哪些陷阱?$condition的哪些值会使它们之间的结果不同 (我似乎记得不久前读过一篇讨论这个问题的文章,但我不记
test
命令这两种否定形式之间是否有什么区别:
if [ ! condition ]; then
fi
if ! [ condition ]; then
fi
第一个命令告诉shell传递参数!条件
进行测试,让程序自行处理否定。另一方面,第二个通过条件
进行测试,并让shell本身消除错误代码
在这两种形式之间进行选择时,我应该注意哪些陷阱?$condition
的哪些值会使它们之间的结果不同
(我似乎记得不久前读过一篇讨论这个问题的文章,但我不记得如何找到它/确切地说是讨论了什么。)
代码>否定以下命令的退出代码:
$ ! test 1 = 1 || echo $? # negate command with true expression
1
如手册页所述,test
(和类似的[
内置)退出,状态由以下表达式确定:
$ test ! 1 = 1 || echo $? # return false expression
1
$ [ ! 1 = 1 ] || echo $?
1
对于给定表达式:
$ test ! 1 = 1 || echo $? # return false expression
1
$ [ ! 1 = 1 ] || echo $?
1
- 在一方面,您否定了以真实表达式状态退出的
test
命令
- 另一方面,您对表达式求反,然后
test
命令(或[
)以其false状态退出
两者的效果相同
所以我认为这些语法是等价的。外部!
允许否定复合测试的优点是:
$ ! [ 1 = 1 -a 2 = 2 ] || echo $?
1
要基于作者对该问题的深刻评论:
- 在
[!condition]
中,!
只是内建的[
的一个参数(测试的有效别名)
内建的;[
/测试
将参数!
解释为否定
![condition]
中,!
是一个shell关键字,它否定任何后跟的命令(在本例中,它恰好是[
)![condition]
语法隐式地告诉您的一件事是,无论[condition]
作为一个整体计算结果是什么,否定都适用于它,因此,如果这就是目的,您就不必担心运算符优先级
性能方面,您选择的语法可能没有多大区别;快速测试建议:
- 如果两种情况下的
完全相同,则将条件
作为参数传递给!
的速度要快得多[
- 如果将
用作关键字,因此您可以通过不考虑优先级来简化条件,它可能会稍微快一点(例如,!
与![0-o1]
;请注意,POSIX规范不鼓励使用[!\(0-o1\)]
和-a
-o
[[/code>而不是[[/code>
,因为[[/code>是一个shell关键字,它在特殊上下文中解析封闭表达式,该上下文:
- 提供更多功能
- 允许您安全地将表达式与
&&
和| |
- 带来的惊喜更少
- 也稍微快一点(尽管在实践中这几乎不重要)
请参阅我的。如果测试
/[
遇到错误,则存在差异。请考虑:
x=abc
if [ ! "$x" -gt 0 ]; then echo "first true"; fi
if ! [ "$x" -gt 0 ]; then echo "second true"; fi
输出为:
bash: [: abc: integer expression expected
second true
与[[…]]
不同,测试
/[
的工作原理与常规实用程序类似,并通过返回2
来发出错误信号。这是一个错误值,当括号外有!
时,shell会将其反转,就像反转测试的常规阴性结果一样
使用[[…]]
时,行为有所不同,因为条件中的语法错误是shell的语法错误,shell本身退出时会出现错误:
if [[ a b ]]; then echo true; else echo false; fi
仅打印
bash: conditional binary operator expected
bash: syntax error near `b'
没有来自echo
s的输出
另一方面,算术测试在[[…]]
so[[“$x”-gt 0]]中的工作方式不同
永远不会给出错误。您可能会注意到,第一组中第三个示例的轻微修改也会报告1
:test!false | echo$?
。这是因为测试正在检查字符串(true
或false
)是否为空。与第一组中的第二个示例类似;用false
替换true
不会改变结果。你是对的。将其替换为我应该是的:表达式。也许你应该注意=
在bash
上工作,但不是dash
。使用POSIX语法更新。不是真正的pit总之,由于很难构建一个实际的场景来实现这一点,但请记住,在![condition]
中,!
是一个shell操作符,否定命令的退出状态,而在[!condition]
中,!
只是[
命令的一个字符串参数。在foo之后=“!bar”
,将[“$foo”]
与[$foo]
进行比较。