我刚刚发现了bash中的set -u
,它帮助我发现了一些以前未被发现的错误。但我也有一个场景,在这个场景中,在计算一些默认值之前,我需要测试变量是否已定义。我想到的最好方法是:
if [ "${variable-undefined}" == undefined ]; then
variable="$(...)"
fi
这种方法可行(只要变量不具有字符串值undefined
)。我想知道是否有更好的方法?
我刚刚发现了bash中的set -u
,它帮助我发现了一些以前未被发现的错误。但我也有一个场景,在这个场景中,在计算一些默认值之前,我需要测试变量是否已定义。我想到的最好方法是:
if [ "${variable-undefined}" == undefined ]; then
variable="$(...)"
fi
这种方法可行(只要变量不具有字符串值undefined
)。我想知道是否有更好的方法?
这是我发现最适合我的方法,受到其他答案的启发:
if [ -z "${varname-}" ]; then
...
varname=$(...)
fi
${varname:-foo}
在 varname
未设置或设置为空字符串时扩展为 foo
;${varname-foo}
只有在 varname
未设置时才扩展为 foo
。 - chepner你可以用几种方法测试未定义的字符串。使用标准的测试条件,看起来像这样:
# 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"错误的情况下安全地使用此表达式。
:
是做什么用的? - PypeBros:
被别名为 true:https://dev59.com/questions/unA75IYBdhLWcg3wkZ6A - Bryce Guintaif [[ ! -v variable ]]; then
variable="$(...)"
fi
请查看http://www.gnu.org/software/bash/manual/bashref.html#Bash-Conditional-Expressions
如果您只想在变量未定义时设置变量,可能更好的方法是执行以下操作:
variable="${variable-$(...)}"
请注意,此方法不能处理已定义但为空的变量。
-v
选项并未添加到bash
中。 - chepneris_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.
}
[[ -n $var ]]
或 [[ $var ]]
而不是 [ ! -z "$var" ]
会更好,你觉得呢?另外,Bash 从 v2 开始就支持变量间接引用,所以这里不需要使用 eval。例如:is_var_defined(){ if (( $# != 1 )); then echo "Expected exactly one argument: variable name as string, e.g., 'my_var'" >&2; return 1; fi; [[ -n ${!1:-} ]]; }
- Six不幸的是,在较旧版本的bash中不支持[[ -v variable ]]
(至少在我使用的Debian Squeeze版本4.1.5中不支持)。
您可以改用子shell,如下所示:
if (true $variable)&>/dev/null; then
variable="$(...)"
fi
if [ "${var+SET}" = "SET" ] ; then
echo "\$var = ${var}"
fi
我不知道${var+value}支持多久了,但至少在4.1.2版本之前是可以使用的。旧版本没有${var+value},只有${var:+value}。区别在于,如果$var设置为非空字符串,则${var:+value}仅计算为"value",而${var+value}也会在$var设置为空字符串时计算为"value"。
如果没有[[ -v var ]]或${var+value},我认为您需要使用另一种方法。可能是一个子shell测试,就像在先前的答案中所描述的那样:
if ( set -u; echo "$var" ) &> /dev/null; then
echo "\$var = ${var}
fi
variable_undefined=""
那么
if [ "${variable_undefined}" == "" ]; then
variable="$(...)"
fi
set -u
模式下,您无法扩展未定义的变量以通过test -z
运行它,因此出现了这个问题。 - Charles Duffy