我如何知道是否在Bash中设置了变量?
例如,如何检查用户是否向函数提供了第一个参数?
function a {
# if $1 is set ?
}
我如何知道是否在Bash中设置了变量?
例如,如何检查用户是否向函数提供了第一个参数?
function a {
# if $1 is set ?
}
当前回答
我总是发现另一个答案中的POSIX表很难找到,所以我的看法是:
parameter expansion | VARIABLE set |
VARIABLE empty |
VARIABLE unset |
---|---|---|---|
${VARIABLE-default} |
$VARIABLE |
"" |
"default" |
${VARIABLE=default} |
$VARIABLE |
"" |
$(VARIABLE="default") |
${VARIABLE?default} |
$VARIABLE |
"" |
exit 127 |
${VARIABLE+default} |
"default" |
"default" |
"" |
${VARIABLE:-default} |
$VARIABLE |
"default" |
"default" |
${VARIABLE:=default} |
$VARIABLE |
$(VARIABLE="default") |
$(VARIABLE="default") |
${VARIABLE:?default} |
$VARIABLE |
exit 127 |
exit 127 |
${VARIABLE:+default} |
"default" |
"" |
"" |
请注意,每个组(前面有和没有冒号)都有相同的设置和未设置的大小写,因此唯一不同的是如何处理空大小写。
对于前面的冒号,空的和未设置的大小写是相同的,因此我将在可能的情况下使用它们(即使用:=,而不仅仅是=,因为空的大小写不一致)。
标题:
set表示VARIABLE为非空(VARIABLE=“something”)空表示VARIABLE为空/空(VARIABLE=“”)未设置表示变量不存在(未设置变量)
值:
$VARIABLE表示结果是变量的原始值。“默认”表示结果是提供的替换字符串。“”表示结果为空(空字符串)。退出127意味着脚本停止执行,退出代码127。$(VARIABLE=“默认”)表示结果为“默认”,VARIABLE(以前为空或未设置)也将设置为“默认值”。
其他回答
我总是使用这个,因为任何第一次看到代码的人都很容易理解:
if [ "$variable" = "" ]
then
echo "Variable X is empty"
fi
如果要检查是否为空;
if [ ! "$variable" = "" ]
then
echo "Variable X is not empty"
fi
就是这样。
我总是发现另一个答案中的POSIX表很难找到,所以我的看法是:
parameter expansion | VARIABLE set |
VARIABLE empty |
VARIABLE unset |
---|---|---|---|
${VARIABLE-default} |
$VARIABLE |
"" |
"default" |
${VARIABLE=default} |
$VARIABLE |
"" |
$(VARIABLE="default") |
${VARIABLE?default} |
$VARIABLE |
"" |
exit 127 |
${VARIABLE+default} |
"default" |
"default" |
"" |
${VARIABLE:-default} |
$VARIABLE |
"default" |
"default" |
${VARIABLE:=default} |
$VARIABLE |
$(VARIABLE="default") |
$(VARIABLE="default") |
${VARIABLE:?default} |
$VARIABLE |
exit 127 |
exit 127 |
${VARIABLE:+default} |
"default" |
"" |
"" |
请注意,每个组(前面有和没有冒号)都有相同的设置和未设置的大小写,因此唯一不同的是如何处理空大小写。
对于前面的冒号,空的和未设置的大小写是相同的,因此我将在可能的情况下使用它们(即使用:=,而不仅仅是=,因为空的大小写不一致)。
标题:
set表示VARIABLE为非空(VARIABLE=“something”)空表示VARIABLE为空/空(VARIABLE=“”)未设置表示变量不存在(未设置变量)
值:
$VARIABLE表示结果是变量的原始值。“默认”表示结果是提供的替换字符串。“”表示结果为空(空字符串)。退出127意味着脚本停止执行,退出代码127。$(VARIABLE=“默认”)表示结果为“默认”,VARIABLE(以前为空或未设置)也将设置为“默认值”。
总结
使用test-n“${var-}”检查变量是否为空(因此也必须定义/设置)。用法:如果测试-n“${var-}”;然后echo“var设置为<$var>”其他的echo“var未设置或为空”传真使用test-n“${var+x}”检查变量是否已定义/设置(即使它是空的)。用法:如果测试-n“${var+x}”;然后echo“var设置为<$var>”其他的echo“var未设置”传真
注意,第一个用例在shell脚本中更常见,这是您通常想要使用的。
笔记
此解决方案应适用于所有POSIX shell(sh、bash、zsh、ksh、dash)这个问题的其他一些答案是正确的,但对于没有shell脚本经验的人来说可能会感到困惑,所以我想提供一个TLDR答案,这对这些人来说是最不困惑的。
解释
要了解此解决方案的工作原理,您需要了解POSIX测试命令和POSIX外壳参数扩展(spec),因此让我们介绍了解答案所需的绝对基础知识。
测试命令计算表达式并返回true或false(通过其退出状态)。如果操作数是非空字符串,则运算符-n返回true。例如,test-n“a”返回true,而test-n“”返回false。现在,要检查变量是否为空(这意味着必须定义它),可以使用test-n“$var”。然而,一些shell脚本有一个选项集(set-u),它会导致对未定义变量的任何引用都会发出错误,因此如果未定义变量var,表达式$var将导致错误。要正确处理这种情况,必须使用变量扩展,如果未定义变量,它将告诉shell用替换字符串替换变量,从而避免上述错误。
变量扩展${var-}表示:如果变量var未定义(也称为“unset”),请用空字符串替换它。因此,如果$var不为空,test-n“${var-}”将返回true,这几乎总是您想要在shell脚本中检查的。如果$var未定义或不为空,则反向检查将是test-z“${var-}”。
现在进入第二个用例:检查变量var是否已定义,无论是否为空。这是一个不太常见的用例,稍微复杂一点,我建议您阅读莱昂内尔的伟大答案,以更好地理解它。
我的首选方式是:
$ var=10
$ if ! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$ unset -v var
$ if ! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set
因此,基本上,如果一个变量被设置,它就变成了“对结果false的否定”(true=“被设置”)。
并且,如果它未设置,它将变成“对结果true的否定”(因为空结果的求值结果为true)(因此将以false=“NOT set”结束)。
为了明确回答OP关于如何确定变量是否已设置的问题,Lionel的回答是正确的:
if test "${name+x}"; then
echo 'name is set'
else
echo 'name is not set'
fi
这个问题已经有很多答案,但没有一个提供真正的布尔表达式来明确区分变量值。
以下是我得出的一些明确表达:
+-----------------------+-------------+---------+------------+
| Expression in script | name='fish' | name='' | unset name |
+-----------------------+-------------+---------+------------+
| test "$name" | TRUE | f | f |
| test -n "$name" | TRUE | f | f |
| test ! -z "$name" | TRUE | f | f |
| test ! "${name-x}" | f | TRUE | f |
| test ! "${name+x}" | f | f | TRUE |
+-----------------------+-------------+---------+------------+
顺便说一下,这些表达式是等价的:测试<表达式><=>〔<表达式>〕
其他需谨慎使用的歧义表达:
+----------------------+-------------+---------+------------+
| Expression in script | name='fish' | name='' | unset name |
+----------------------+-------------+---------+------------+
| test "${name+x}" | TRUE | TRUE | f |
| test "${name-x}" | TRUE | f | TRUE |
| test -z "$name" | f | TRUE | TRUE |
| test ! "$name" | f | TRUE | TRUE |
| test ! -n "$name" | f | TRUE | TRUE |
| test "$name" = '' | f | TRUE | TRUE |
+----------------------+-------------+---------+------------+