test 或 [ 或 [[ 在 bash shell 和其他 shell 之间更可移植吗?

test 或 [ 或 [[ 在 bash shell 和其他 shell 之间更可移植吗?

我知道我能做到

$ [ -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 中,但不存在于shdash或其他各种更简单的 shell 中。

因此,为了使您的脚本可移植,请使用[ ],testif ... 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常见问题解答

相关内容