我知道我能做到
$ [ -w /home/durrantm ] && echo "writable"
writable
或者
$ test -w /home/durrantm && echo "writable"
writable
或者
$ [[ -w /home/durrantm ]] && echo "writable"
writable
我喜欢使用第三种语法。它们在所有方面以及所有负面和边缘情况下都是等价的吗?可移植性是否有任何差异,例如 Ubuntu 上的 bash 和 OS X 或旧/新 bash 版本(例如 4.0 之前/之后)之间的差异,它们是否都以相同的方式扩展表达式?
答案1
是的,存在差异。最便携的是test
或[ ]
。这些都是POSIXtest
规范。
该if ... fi
结构也是由 POSIX 定义并且应该是完全便携的。
该[[ ]]
功能ksh
也存在于某些版本中bash
(所有现代的),在其他 shell 中zsh
,也许在其他 shell 中,但不存在于sh
或dash
或其他各种更简单的 shell 中。
因此,为了使您的脚本可移植,请使用[ ]
,test
或if ... fi
.
答案2
[
是命令的同义词test
,同时也是bash 内置和单独的命令。但是[[
是一个bash 关键字并且仅适用于某些版本。因此,出于可移植性的原因,您最好使用单个[]
或test
[ -w "/home/durrantm" ] && echo "writable"
答案3
请注意,这与建筑[] && cmd
不同。if .. fi
有时它的行为非常相似,您可以[] && cmd
使用if .. fi
.但只是有时。如果您有多个命令要执行 if 条件,或者您需要if .. else .. fi
小心并了解其逻辑。
举几个例子:
[ -z "$VAR" ] && ls file || echo wiiii
不一样
if [ -z $VAR ] ; then
ls file
else
echo wiii
fi
因为 ifls
会失败,echo
将会被执行,而 . 不会发生这种情况if
。
另一个例子:
[ -z "$VAR" ] && ls file && echo wiii
不等于
if [ -z "$VAR" ] ; then
ls file
echo $wiii
fi
虽然这个结构的作用是一样的
[ -z "$VAR" ] && { ls file ; echo wiii ; }
请注意;
after echo 很重要并且必须存在。
所以继续上面的陈述我们可以说
[] && cmd
== 如果第一个命令成功则执行下一个命令
if .. fi
== if 条件(也可能是测试命令)然后执行命令
[
因此仅用于和[[
使用之间的可移植性[
。
if
与 POSIX 兼容。因此,如果您必须在两者之间做出选择[
,if
请考虑您的任务和预期行为。
答案4
为了便于移植,请使用test
/ [
。但是,如果您不需要可移植性,为了您自己和其他人阅读您的脚本的理智,请使用[[
. :)
另请What is the difference between test, [ and [[ ?
参见Bash常见问题解答。