After reading 24.2. Local Variables, I thought that declaring a variable var
with the keyword local
meant that var
's value was only accessible within the block of code delimited by the curly braces of a function.
However, after running the following example, I found out that var
can also be accessed, read and written from the functions invoked by that block of code — i.e. even though var
is declared local
to outerFunc
, innerFunc
is still able to read it and alter its value.
#!/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}]"
Output:
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:]
Q: Is that a bug in my shell (bash 4.3.42, Ubuntu 16.04, 64bit) or is it the expected behavior ?
EDIT: Solved. As noted by @MarkPlotnick, this is indeed the expected behavior.
Best Answer
Shell variables have a dynamic scope. If a variable is declared as local to a function, that scope remains until the function returns, including during calls to other functions.
There are two exceptions:
in ksh93, if a function is defined with the standard
function_name () { … }
syntax, then its local variables obey dynamic scoping. But if a function is defined with the ksh syntaxfunction function_name { … }
then its local variable obey lexical/static scoping, so they are not visible in other functions called by this.the
zsh/private
autoloadable plugin inzsh
provides with aprivate
keyword/builtin which can be used to declare a variable with static scope.ash, bash, pdksh and derivatives, bosh only have dynamic scoping.