重要的是要记住,空的 shell 变量与未设置的 shell 变量不同——尽管不能使用[ test ]
. 所test
能做的就是报告变量扩展的值 - 决定这一点的是参数扩展。例如:
var=value
echo "${var+I am \$var and I am set. I am currently ${var:+not} empty.}"
###OUTPUT###
I am $var and I am set. I am currently not empty.
再次:
var=
echo "${var+I am \$var and I am set. I am currently ${var:+not} empty.}"
###OUTPUT###
I am $var and I am set. I am currently empty.
与[ test ]
:
{ _nstr() { echo 'I just evaluated a ""null string!' ; }
[ -z "$var" ] && _nstr
[ -z "" ] && _nstr
unset var
[ -z "$var" ] && _nstr
echo "${var+I am \$var and I am set. I am currently ${var:+not} empty.}"
}
###OUTPUT###
I just evaluated a ""null string!
I just evaluated a ""null string!
I just evaluated a ""null string!
希望这能把它带回家:
var=value
[ -z "${var+}" ] && _nstr
###OUTPUT###
I just evaluated a ""null string!
如果您想可移植地确定变量是否为空,则可以这样做:
${var:+false} [ -n "${var+1}" ] && echo \$var is set and null
我认为您可以很好地利用 shell 的参数扩展来处理此类情况,在某些情况下甚至可以用一块石头杀死两只鸟(参见第一个示例)。这绝对应该是便携式的。以下是开放组的 POSIX shell 指南的不完整复制/粘贴,可在此处找到:http: //pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
${parameter:-word}
- 使用默认值。如果参数是
unset
or null
,则替换 word 的扩展;否则,应替换参数的值。
${parameter:=word}
- 分配默认值。如果 parameter 是
unset
or null
,则将 word 的扩展分配给 parameter。在所有情况下,应替换参数的最终值。只能以这种方式分配变量,而不是位置参数或特殊参数。
${parameter:?[word]}
- 如果为 Null 或未设置,则指示错误。如果参数是
unset
or null
,则 word 的扩展(或如果 word 省略,则指示它未设置的消息)应写入标准错误,并且 shell 以非零退出状态退出。否则,应替换参数的值。交互式外壳不需要退出。
${parameter:+word}
- 使用替代价值。如果参数是
unset
or null
,null
则应替换;否则,用词的扩展代替。
例子:
${parameter:-word}
- 在此示例中,
ls
仅当x
isnull
或时才执行unset
。($( ls)
命令替换符号在命令替换中解释。)
${x:-$(ls)}
${parameter:=word}
% unset X
% echo ${X:=abc}
abc
编辑:
我刚刚注意到 Ashish 的单线,因为粘贴它感觉有点便宜,我想做点什么。所以这里有一个 POSIX 参数扩展 set-test one-liner:
_JAIL="" ; echo "_JAIL is ${_JAIL:-unset or null.}"
好吧,我猜还是很便宜。
编辑2:
所以我只是注意到了这一点:“......虽然这些脚本适用于我现在编写的脚本,但我想知道一种方法,它可以在任何合理兼容的类似 sh 的 shell 中工作,即使在比 Linux 更晦涩的环境中也是如此具有 GNU 用户空间和 bash 或 dash 的 PC..."
抱歉,我个人不是专家,但我首先选择了以下方法来定义重要的 shell 变量,这些变量在挖掘了一些相当熟练编写的 initramfs busybox 脚本之后可能会或可能不会被传递。它几乎可以在任何地方按预期工作。
这有点漂亮,因为您只有在用户没有定义变量时才将变量设置为默认条件,而无需任何额外的工作来检查它们是否确实如此。当然还有很多其他用途,我只是不够聪明,无法像我应该的那样使用它们。
_VAR1=${1:-/default/path} ; _VAR2=${2:-"$_default_size"}
编辑3:
phs 正确地指定他的方法测试空变量而不是问题中提出的空变量。根据是否使用中心冒号,此方法可以执行相同的操作。我已经从下面的 POSIX 指南中复制了一个废话表来证明这一点。
{subs='substitute'; params='parameters'; assn='assign'; err='error'}
"$parameter" == |set && !null |set && null| !set
------------------ ------------- ----------- ----------
${parameter:-word} | subs params | subs word | subs word
------------------ ------------- ----------- ----------
${parameter-word} | subs params | subs null | subs word
------------------ ------------- ----------- ----------
${parameter:=word} | subs params | assn word | assn word
------------------ ------------- ----------- ----------
${parameter=word} | subs params | subs null | assn word
------------------ ------------- ----------- ----------
${parameter:?word} | subs params | err; exit | err; exit
------------------ ------------- ----------- ----------
${parameter?word} | subs params | subs null | err; exit
------------------ ------------- ----------- ----------
${parameter:+word} | subs word | subs null | subs null
------------------ ------------- ----------- ----------
${parameter+word} | subs word | subs word | subs null