O comportamento muda do Bash 4.0 em diante e parece uma correção de bug de escopo variável. O comportamento do seu código é alterado com base na existência de variáveis globais com o mesmo nome.
Nas versões anteriores a 4.0
- Se você tiver um
variable
global definido com o mesmo nome que o local,${variable+override}
funcionará conforme documentado. - Se você não tiver uma variável global,
${variable+override}
usará o valor de substituição.
Isso é o oposto do que você normalmente esperaria de um problema de escopo global. Talvez ter as causas globais local
para configurar a variável de maneira diferente em versões anteriores do Bash ou talvez +
procure variáveis de uma maneira diferente.
Como o @rush mencionou, você obtém um comportamento consistente em todas as versões se usar ${foo:+defined}
. Também não consegui encontrar muita documentação sobre como usar apenas o símbolo de mais, exceto as referências ao uso de @choroba e @chepner acrescentaram que ${1+"$@"}
para o qual há um teste na origem. man bash
explica que Omitir os resultados do cólon em um teste apenas para um parâmetro que não foi definido .
Usando a seguinte função modificada (ter a função com o mesmo nome da variável não impactou em nada, mas foi a primeira coisa que achei que poderia estar provocando o bug):
foo() {
echo "global bar [${bar+defined}]"
local bar
echo "local bar [${bar+defined}]"
}
4.0.0 (1) -release
$ 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) -release
$ 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) -release
$ 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) -release
$ echo $BASH_VERSION
2.05b.0(1)-release
$ unset bar
$ foo
global bar []
local bar [defined]
$ bar=test
$ foo
global bar [defined]
local bar []