Eli*_*igo 21 bash conditional if-statement
在我从一名前员工继承的许多脚本中,我一直看到这种模式:
if (true $SOME_VAR)&>/dev/null; then
...
fi
Run Code Online (Sandbox Code Playgroud)
或者这个
(true $SOME_VAR)&>/dev/null || SOME_VAR="..."
Run Code Online (Sandbox Code Playgroud)
人工页面true说它总是返回true,因此我一直在想,这些检查有什么意义?在第一种情况下,then部件始终执行,在第二种情况下,从不执行右手部件.
jwo*_*der 24
如果set -u(aka set -o nounset)生效,true $SOME_VAR则在$SOME_VAR未定义时将失败.因此,这是一种测试变量是否已定义的方法.
mkl*_*nt0 14
为了补充jwodder的有用答案和Fred的有用答案:
在Bash v4.2 +中
,可以使用不那么模糊和更有效的-v运算符来测试变量是否被定义[1](注意不必 $使用):
[[ -v SOME_VAR ]]
在较旧的Bash版本和符合POSIX的脚本中,使用Fred的基于参数扩展的方法,这种方法也比(true ...)方法更有效.
如果意图是简单地提供默认值,如在(true $SOME_VAR)&>/dev/null || SOME_VAR="..."习语中,使用kojiro建议的(POSIX兼容)技术,也基于参数扩展:
SOME_VAR=${SOME_VAR-...} # keep $SOME_VAR value or default to '...'
Toby Speight建议另一个符合POSIX的变体${SOME_VAR=...},它直接更新变量如果未定义,则使用默认值; 然而,它具有扩展到(结果)值的副作用- 这可能是也可能不是所希望的.抑制扩展的简洁但又略微模糊的方法是将扩展传递给冒号(null)实用程序(:),该实用程序扩展,但忽略其参数(与true用于相同目的相比,它可能稍微有点混乱):
: ${SOME_VAR=...} # set $SOMEVAR to '...' only if not defined
注意,示出的所有参数扩展/上述具有变体其放置:在操作者面前,然后不仅作用在可变是未定义的,而且当它被定义,但空(包含空字符串): ,,
${SOME_VAR:+...}
可以说,该变型行为通常是更强大的技术,特别是当没有打开when ()时,未定义的变量会扩展为null(空)字符串.${SOME_VAR:-...}${SOME_VAR:=...}set -uset -o nunset
要添加到jwodder的解释:
使用(...)around true $SOME_VAR来创建子shell对于这种有些模糊的测试,对于变量存在按预期工作是至关重要的.
没有子shell,整个脚本将中止.
对子壳的需求使得该技术不仅模糊不清,而且效率低下(尽管偶尔使用时不会引起注意).
set -u(set -o nounset)恰好没有生效,该技术会将所有变量视为已定义.使用子shell,只有子shell中止,这在其退出代码中反映到当前shell 1:,如果子shell中止(变量不存在),0否则.
因此,(true ...)如果变量存在,则命令仅评估(概念上)true.
&>/dev/null 如果变量不存在,则禁止从子shell中发出的错误消息.
true永远不会产生任何输出,因此它足以使用(true $SOME_VAR)2>/dev/null(仅抑制stderr) - 这种改变使得技术符合POSIX(尽管仍然不可取).这不仅是set -u(set -o nounset)语句里面是打开的访问的情况下中止未定义变量的脚本-调用bash与命令行选项明确-u有同样的效果.
[1]从Bash v4.3开始,您还可以测试数组变量是否具有指定索引的元素; 例如:
a=( one two ); [[ -v a[0] ]]成功,因为0存在索引的数组元素; 与关联数组类似.
以下可能是等效的,更直接的:
if [ "${SOME_VAR+x}" ] then
...
fi
Run Code Online (Sandbox Code Playgroud)
或者,在作业案例中:
[ "${SOME_VAR+x}" ] || SOME_VAR="..."
Run Code Online (Sandbox Code Playgroud)
的+膨胀操作扩展到一个空字符串,如果该变量被复位,并且x,如果它被分配(分配一个空字符串仍然意味着分配的).在这种情况下,您可以替换x任何您想要的(除了空字符串).
还有一个${SOME_VAR:+x}变种.区别在于空字符串::+如果为变量分配了空字符串,则+扩展为空字符串(x如果分配了值,则扩展为空字符串,即使它是空字符串).