在 Bash 3.00.16 中,打印以下内容defined
,在 Bash 4.2.24 中打印undefined
:
my_test() {
local foo
if [ -n "${foo+defined}" ]
then
echo defined
else
echo undefined
fi
}
my_test
我找不到任何明显相关的内容bash 变化页。
- 这是什么时候改变的?
- 这被认为是错误修复,还是其他更改的副作用?换句话说,当前的行为是否可以认为是稳定的?
答案1
从 Bash 4.0 开始,该行为发生了变化,看起来像是一个可变范围的错误修复。代码的行为会根据同名全局变量的存在而改变。
在 4.0 之前的版本中
variable
如果您定义了与本地同名的全局,${variable+override}
则将按记录工作。- 如果没有全局变量,
${variable+override}
将使用覆盖值。
这与您通常对全球范围问题的预期相反。也许有全局原因local
在早期版本的 Bash 中以不同的方式设置变量,或者可能+
以不同的方式查找变量。
正如 @rush 提到的,如果您使用${foo:+defined}
.我也找不到太多关于仅使用加号的文档,除了 @choroba 和 @chepner 补充道,这${1+"$@"}
源代码中有测试的使用参考。man bash
解释了这一点省略冒号会导致仅测试未设置的参数。
使用以下修改后的函数(将函数命名为与变量相同不会影响任何内容,但这是我认为可能触发错误的第一件事):
foo() {
echo "global bar [${bar+defined}]"
local bar
echo "local bar [${bar+defined}]"
}
4.0.0(1)-发布
$ echo $BASH_VERSION
4.0.0(1)-release
$ unset bar
$ foo
global bar []
local bar []
$ bar=test
$ foo
global bar [defined]
local bar []
3.2.0(1)-发布
$ echo $BASH_VERSION
3.2.0(1)-release
$ unset bar
$ foo
global bar []
local bar [defined]
$ bar=test
$ foo
global bar [defined]
local bar []
3.00.16(1)-发布
$ echo $BASH_VERSION
3.00.16(1)-release
$ unset bar
$ foo
global bar []
local bar [defined]
$ bar=test
$ foo
global bar [defined]
local bar []
2.05b.0(1)-发布
$ echo $BASH_VERSION
2.05b.0(1)-release
$ unset bar
$ foo
global bar []
local bar [defined]
$ bar=test
$ foo
global bar [defined]
local bar []