Bash 中的变量定义更改

Bash 中的变量定义更改

在 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}.我也找不到太多关于仅使用加号的文档,除了${1+"$@"}源代码中有测试的使用参考。 @choroba 和 @chepner 补充道,这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  []

相关内容