Después de leer 24.2. Variables locales , pensé que declarar una variable var
con la palabra clave local
significaba que var
solo se podía acceder al valor dentro del bloque de código delimitado por las llaves de una función.
Sin embargo, después de ejecutar el siguiente ejemplo, descubrí que var
también se puede acceder, leídos y escritos desde las funciones invocadas por ese bloque de código - es decir, a pesar de que var
se declara local
a outerFunc
, innerFunc
todavía es capaz de leer y alterar su 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}]"
Salida:
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: ¿Es un error en mi shell (bash 4.3.42, Ubuntu 16.04, 64 bits) o es el comportamiento esperado?
EDITAR: Resuelto. Como señaló @MarkPlotnick, este es de hecho el comportamiento esperado.
var
esté vacío?var
está configurado globalmenteinnerFunc
, entonces ¿por qué no se mantiene hasta el final del guión?Respuestas:
Las variables de shell tienen un alcance dinámico . Si una variable se declara como local para una función, ese alcance permanece hasta que la función regrese.
Hay dos excepciones:
en ksh93, si una función se define con la
function_name () { … }
sintaxis estándar , entonces sus variables locales obedecen al alcance dinámico. Pero si una función se define con la sintaxis ksh,function function_name { … }
entonces su variable local obedece al ámbito léxico / estático, por lo que no son visibles en otras funciones llamadas por esto.El
zsh/private
complemento autocargable enzsh
proporciona unaprivate
palabra clave / incorporado que se puede utilizar para declarar una variable con alcance estático.ash, bash, pdksh y derivados, bosh solo tienen alcance dinámico.
fuente
local
?typeset
odeclare
olocal
declaración, el alcance es hasta que se devuelve la función. Sin tal declaración, el alcance es global.No es un error, la llamada dentro del contexto del externalFunc usa esa copia local de $ var. El "local" en outsideFunc significa que lo global no ha cambiado. Si llama a innerFunc fuera de outsideFunc, entonces habrá un cambio en el $ var global, pero no en el $ var local del externalFunc. Si agrega "local" a innerFunc, entonces $ var de externalFunc no se cambiaría, en esencia, habría 3 de ellos:
usar el formato de espacio de nombres de Perl, más o menos.
fuente
Puede usar una función para forzar el alcance local:
Ejemplo:
Resultado:
Fuente
fuente
En
function innerFunc()
elvar='new value'
no se declaró como local , por lo tanto, está disponible en alcance visible (una vez que se ha llamado a la función).Por el contrario, en
function outerFunc()
ellocal var='initial value'
se declaró como local , por lo tanto, no está disponible en el ámbito global (incluso si se ha llamado a la función).Como
innerFunc()
se llamó como hijo deouterFunc()
, var está dentro del ámbito local deouterFunc()
.man 1 bash
puede ayudar a aclararEl comportamiento que se espera implícita en la descripción podría lograrse mediante la que se declara
local var='new value
enfunction innerFunc()
.Como han dicho otros, esto no es un error en el shell bash. Todo funciona como debería.
fuente
var
en el ámbito global, después de llamarinnerFunc
a travésoutFunc
, no se imprimenew value
.