在Bash中,如何testingvariables是否以“-u”模式定义

我刚刚在bash中发现了set -u ,它帮助我find了几个以前看不见的错误。 但是我也有一个场景,在计算某个默认值之前,我需要testing是否定义了一个variables。 我为此得出的最好的是:

 if [ "${variable-undefined}" == undefined ]; then variable="$(...)" fi 

它工作(只要该variables没有undefined的string值)。 我想知道是否有更好的方法?

什么不起作用:testing零长度string

您可以用几种方法testing未定义的string。 使用标准的testing条件如下所示:

 # Test for zero-length string. [ -z "$variable" ] || variable='foo' 

但是,这不会与set -u一起使用。

什么作品:有条件的作业

或者,你可以使用条件赋值,这是一个更类似Bash的方式来做到这一点。 例如:

 # Assign value if variable is unset or null. : "${variable:=foo}" 

由于Bash处理这个expression式的扩展的方式,你可以安全地在set -u使用这个,而不会得到一个“bash:variable:unbound variable”的错误。

这是我发现最适合我的方式,从其他答案中获得灵感:

 if [ -z "${varname-}" ]; then ... varname=$(...) fi 

在bash 4.2和更新版本中,有一个明确的方法来检查是否设置了一个variables,即使用-v。 这个问题的例子可以这样实现:

 if [[ ! -v variable ]]; then variable="$(...)" fi 

请参阅http://www.gnu.org/software/bash/manual/bashref.html#Bash-Conditional-Expressions

如果你只想设置variables,如果它还没有设置,你可能更喜欢沿着这些线做一些事情:

variable="${variable-$(...)}"

请注意,这不处理已定义的空variables。

上面的答案不是dynamic的,例如,如何testingvariables名为“dummy”的variables是否定义? 尝试这个:

 is_var_defined() { if [ $# -ne 1 ] then echo "Expected exactly one argument: variable name as string, eg, '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. } 

相关: 如何检查variables是否在Bash中设置?

在脚本的开始,你可以用一个空值定义你的variables

 variable_undefined="" 

然后

 if [ "${variable_undefined}" == "" ]; then variable="$(...)" fi 

旧版本的bash不支持[[ -v variable ]] (至less在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}有多远,但至less可以早于4.1.2。 旧版本没有$ {var + value},他们只有$ {var:+ value}。 不同之处在于如果$ var被设置为非空string,则$ {var:+ value}将仅评估为“value”,而$ var被设置为空的时候$ {var + value}也会评估为“value”串。

如果没有[[-v var]]或$ {var + value},我想你必须使用另一种方法。 可能是在之前的回答中描述的一个子shelltesting:

 if ( set -u; echo "$var" ) &> /dev/null; then echo "\$var = ${var} fi 

如果你的shell进程已经“set -u”活动了,它就会在子shell中处于活动状态,而不需要再次设置“-u”,但是在subhell命令中包括它也可以让解决scheme在父进程没有启用“set -u”。

(您也可以使用其他进程(如“printenv”或“env”)来testingvariables是否存在,但只有在variables被导出时才能使用)。