Depois de ler 24.2. Variáveis locais , pensei que declarar uma variável var
com a palavra-chave local
significava que var
o valor de s só era acessível dentro do bloco de código delimitado pelas chaves de uma função.
No entanto, depois de executar o exemplo a seguir, descobri que var
também pode ser acessado, lido e escrito das funções invocadas por esse bloco de código - ou seja, mesmo que var
seja declarada local
a outerFunc
, innerFunc
ainda é capaz de lê-lo e alterar seu valor.
#!/usr/bin/env bash
function innerFunc() {
var='new value'
echo "innerFunc: [var:${var}]"
}
function outerFunc() {
local var='initial value'
echo "outerFunc: before innerFunc: [var:${var}]"
innerFunc
echo "outerFunc: after innerFunc: [var:${var}]"
}
echo "global: before outerFunc: [var:${var}]"
outerFunc
echo "global: after outerFunc: [var:${var}]"
Saída:
global: before outerFunc: [var:] # as expected, `var` is not accessible outside of `outerFunc`
outerFunc: before innerFunc: [var:initial value]
innerFunc: [var:new value] # `innerFunc` has access to `var` ??
outerFunc: after innerFunc: [var:new value] # the modification of `var` by `innerFunc` is visible to `outerFunc` ??
global: after outerFunc: [var:]
P: Isso é um bug no meu shell (bash 4.3.42, Ubuntu 16.04, 64bit) ou é o comportamento esperado?
EDIT: resolvido. Conforme observado por @MarkPlotnick, esse é realmente o comportamento esperado.
var
esteja vazio?var
está definido globalmenteinnerFunc
, então por que não permanece até o final do script?Respostas:
Variáveis de shell têm um escopo dinâmico . Se uma variável for declarada como local para uma função, esse escopo permanecerá até que a função retorne.
Existem duas exceções:
no ksh93, se uma função é definida com a
function_name () { … }
sintaxe padrão , suas variáveis locais obedecem ao escopo dinâmico. Mas se uma função é definida com a sintaxe kshfunction function_name { … }
, sua variável local obedece ao escopo lexical / estático, portanto, elas não são visíveis em outras funções chamadas por isso.o
zsh/private
plug-in de carregamento automáticozsh
fornece umaprivate
palavra - chave / builtin que pode ser usada para declarar uma variável com escopo estático.ash, bash, pdksh e derivados, o bosh possui escopo dinâmico.
fonte
local
?typeset
oudeclare
oulocal
declaração, o escopo é até que a função retorna. Sem essa declaração, o escopo é global.Não é um bug, a chamada dentro do contexto do outerFunc usa essa cópia local de $ var. O "local" em outerFunc significa que o global não é alterado. Se você chamar innerFunc fora de outerFunc, haverá uma alteração no $ var global, mas não no $ var local do outerFunc. Se você adicionou "local" ao innerFunc, o $ var do outerFunc não seria alterado - em essência, haveria três deles:
para usar o formato de espaço para nome do Perl, mais ou menos.
fonte
Você pode usar uma função para forçar o escopo local:
Exemplo:
Resultado:
Fonte
fonte
function innerFunc()
Novar='new value'
não foi declarado como locais , portanto, ele está disponível em âmbito visível (uma vez que a função foi chamado).Por outro lado,
function outerFunc()
nalocal var='initial value'
foi declarado como locais , portanto, ele não está disponível no escopo global (mesmo que a função foi chamado).Como
innerFunc()
foi chamado como filho deouterFunc()
, var está dentro do escopo local deouterFunc()
.man 1 bash
pode ajudar a esclarecerO comportamento implícito que é esperado na descrição poderia ser alcançado por declarar
local var='new value
emfunction innerFunc()
.Como outros já declararam, isso não é um bug no shell bash. Tudo está funcionando como deveria.
fonte
var
no escopo global, depois de chamarinnerFunc
atravésoutFunc
, não imprimenew value
.