在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被导出时才能使用)。