我刚刚在bash中发现了set -u
,它帮助我找到了几个以前看不见的错误。但我还有一个场景,我需要在计算某个默认值之前测试是否定义了变量。我想出的最好的是:
if [ "${variable-undefined}" == undefined ]; then
variable="$(...)"
fi
有效(只要变量没有字符串值undefined
)。我想知道是否有更好的方法?
答案 0 :(得分:52)
这是我发现最适合我的,从其他答案中获取灵感:
if [ -z "${varname-}" ]; then
...
varname=$(...)
fi
答案 1 :(得分:30)
您可以通过几种方式测试未定义的字符串。使用标准测试条件如下所示:
# Test for zero-length string.
[ -z "$variable" ] || variable='foo'
然而,这不适用于set -u
。
或者,您可以使用条件赋值,这是一种类似Bash的方法。例如:
# Assign value if variable is unset or null.
: "${variable:=foo}"
由于Bash处理此表达式扩展的方式,您可以安全地将其与set -u
一起使用,而不会出现“bash:variable:unbound variable”错误。
答案 2 :(得分:7)
在bash 4.2及更新版本中,有一种明确的方法来检查是否设置了一个变量,即使用-v。 然后可以像这样实现问题的例子:
if [[ ! -v variable ]]; then
variable="$(...)"
fi
请参阅http://www.gnu.org/software/bash/manual/bashref.html#Bash-Conditional-Expressions
如果您只想设置变量,如果尚未设置变量,您可能更喜欢按照以下方式执行操作:
variable="${variable-$(...)}"
请注意,这不会处理已定义但空的变量。
答案 3 :(得分:4)
上面的答案不是动态的,例如,如何测试变量,名称为“dummy”?试试这个:
is_var_defined()
{
if [ $# -ne 1 ]
then
echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
exit 1
fi
# Tricky. Since Bash option 'set -u' may be enabled, we cannot directly test if a variable
# is defined with this construct: [ ! -z "$var" ]. Instead, we must use default value
# substitution with this construct: [ ! -z "${var:-}" ]. Normally, a default value follows the
# operator ':-', but here we leave it blank for empty (null) string. Finally, we need to
# substitute the text from $1 as 'var'. This is not allowed directly in Bash with this
# construct: [ ! -z "${$1:-}" ]. We need to use indirection with eval operator.
# Example: $1="var"
# Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"
# Code execute: [ ! -z ${var:-} ]
eval "[ ! -z \${$1:-} ]"
return $? # Pedantic.
}
答案 4 :(得分:1)
在脚本的开头,您可以使用空值
定义变量variable_undefined=""
然后
if [ "${variable_undefined}" == "" ]; then
variable="$(...)"
fi
答案 5 :(得分:1)
旧版本的bash不支持不幸[[ -v variable ]]
(至少不是我在Debian Squeeze上的4.1.5版本)
您可以使用子shell,如下所示:
if (true $variable)&>/dev/null; then
variable="$(...)"
fi
答案 6 :(得分:0)
if [ "${var+SET}" = "SET" ] ; then
echo "\$var = ${var}"
fi
我不知道支持$ {var + value}多远,但它至少可以追溯到4.1.2。旧版本没有$ {var + value},它们只有$ {var:+ value}。区别在于,如果$ var设置为非空字符串,$ {var:+ value}将仅评估为“value”,而$ {var + value}也将评估为“value” $ var设置为空字符串。
没有[[-v var]]或$ {var + value}我认为你必须使用另一种方法。可能是前面答案中描述的子壳测试:
if ( set -u; echo "$var" ) &> /dev/null; then
echo "\$var = ${var}
fi
如果你的shell进程已经“set -u”处于活动状态,那么它也会在子shell中处于活动状态,而不需要再次使用“set -u”,但是在subshell命令中将它包括在内也可以使解决方案也能正常运行父进程没有启用“set -u”。
(您还可以使用“printenv”或“env”等其他进程来测试变量的存在,但是只有在导出变量时它才有效。)