Scope of Local Variables in Shell Functions

Clash Royale CLAN TAG#URR8PPP
up vote
16
down vote
favorite
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.
Run It Online
#!/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.
bash shell shell-script variable function
add a comment |Â
up vote
16
down vote
favorite
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.
Run It Online
#!/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.
bash shell shell-script variable function
It is the expected behavior
â fpmurphy1
May 11 '16 at 17:09
add a comment |Â
up vote
16
down vote
favorite
up vote
16
down vote
favorite
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.
Run It Online
#!/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.
bash shell shell-script variable function
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.
Run It Online
#!/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.
bash shell shell-script variable function
bash shell shell-script variable function
edited Oct 19 '17 at 17:35
lesmana
13.9k105571
13.9k105571
asked May 11 '16 at 16:22
865719
181127
181127
It is the expected behavior
â fpmurphy1
May 11 '16 at 17:09
add a comment |Â
It is the expected behavior
â fpmurphy1
May 11 '16 at 17:09
It is the expected behavior
â fpmurphy1
May 11 '16 at 17:09
It is the expected behavior
â fpmurphy1
May 11 '16 at 17:09
add a comment |Â
4 Answers
4
active
oldest
votes
up vote
14
down vote
Shell variables have a dynamic scope. If a variable is declared as local to a function, that scope remains until the function returns.
There is an exception: in ATT ksh, 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 syntax function function_name â¦àthen its local variable obey lexical scoping, so they are not visible in other functions called by this. But bash, mksh and zsh only have dynamic scoping.
add a comment |Â
up vote
4
down vote
It isn't a bug, the call inside the context of the outerFunc uses that local copy of $var. The "local" in outerFunc means the global isn't changed. If you call innerFunc outside of outerFunc, then there will be a change to the global $var, but not the outerFunc's local $var. If you added "local" to innerFunc, then outerFunc's $var wouldn't be changed - in essence, there'd be 3 of them:
- $global::var
- $outerFunc::var
- $innerFunc::var
to use Perl's namespace format, sort of.
add a comment |Â
up vote
1
down vote
You can use a function to force local scope:
sh_local()
eval "$(set)" command eval '"$@"'
Example:
x()
z='new value'
printf 'function x, z = [%s]n' "$z"
y()
z='initial value'
printf 'function y before x, z = [%s]n' "$z"
sh_local x
printf 'function y after x, z = [%s]n' "$z"
printf 'global before y, z = [%s]n' "$z"
y
printf 'global after y, z = [%s]n' "$z"
Result:
global before y, z =
function y before x, z = [initial value]
function x, z = [new value]
function y after x, z = [initial value]
global after y, z = [initial value]
Source
add a comment |Â
up vote
0
down vote
In function innerFunc() the var='new value' wasn't declared as local, therefore it's available in the global scope (once the function has been called).
Conversely, in function outFunc() the local var='initial value' was declared as local, therefore it's not available in the global scope (even if the function has been called).
The implied behavior that's expected in the description could be achieved by declaring local var='new value in function innerFunc().
24.2. Local Variables says all that, too.
As others have stated, this is not a bug in the bash shell. Everything's functioning as it should.
add a comment |Â
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
14
down vote
Shell variables have a dynamic scope. If a variable is declared as local to a function, that scope remains until the function returns.
There is an exception: in ATT ksh, 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 syntax function function_name â¦àthen its local variable obey lexical scoping, so they are not visible in other functions called by this. But bash, mksh and zsh only have dynamic scoping.
add a comment |Â
up vote
14
down vote
Shell variables have a dynamic scope. If a variable is declared as local to a function, that scope remains until the function returns.
There is an exception: in ATT ksh, 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 syntax function function_name â¦àthen its local variable obey lexical scoping, so they are not visible in other functions called by this. But bash, mksh and zsh only have dynamic scoping.
add a comment |Â
up vote
14
down vote
up vote
14
down vote
Shell variables have a dynamic scope. If a variable is declared as local to a function, that scope remains until the function returns.
There is an exception: in ATT ksh, 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 syntax function function_name â¦àthen its local variable obey lexical scoping, so they are not visible in other functions called by this. But bash, mksh and zsh only have dynamic scoping.
Shell variables have a dynamic scope. If a variable is declared as local to a function, that scope remains until the function returns.
There is an exception: in ATT ksh, 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 syntax function function_name â¦àthen its local variable obey lexical scoping, so they are not visible in other functions called by this. But bash, mksh and zsh only have dynamic scoping.
answered May 11 '16 at 22:44
Gilles
515k12110231551
515k12110231551
add a comment |Â
add a comment |Â
up vote
4
down vote
It isn't a bug, the call inside the context of the outerFunc uses that local copy of $var. The "local" in outerFunc means the global isn't changed. If you call innerFunc outside of outerFunc, then there will be a change to the global $var, but not the outerFunc's local $var. If you added "local" to innerFunc, then outerFunc's $var wouldn't be changed - in essence, there'd be 3 of them:
- $global::var
- $outerFunc::var
- $innerFunc::var
to use Perl's namespace format, sort of.
add a comment |Â
up vote
4
down vote
It isn't a bug, the call inside the context of the outerFunc uses that local copy of $var. The "local" in outerFunc means the global isn't changed. If you call innerFunc outside of outerFunc, then there will be a change to the global $var, but not the outerFunc's local $var. If you added "local" to innerFunc, then outerFunc's $var wouldn't be changed - in essence, there'd be 3 of them:
- $global::var
- $outerFunc::var
- $innerFunc::var
to use Perl's namespace format, sort of.
add a comment |Â
up vote
4
down vote
up vote
4
down vote
It isn't a bug, the call inside the context of the outerFunc uses that local copy of $var. The "local" in outerFunc means the global isn't changed. If you call innerFunc outside of outerFunc, then there will be a change to the global $var, but not the outerFunc's local $var. If you added "local" to innerFunc, then outerFunc's $var wouldn't be changed - in essence, there'd be 3 of them:
- $global::var
- $outerFunc::var
- $innerFunc::var
to use Perl's namespace format, sort of.
It isn't a bug, the call inside the context of the outerFunc uses that local copy of $var. The "local" in outerFunc means the global isn't changed. If you call innerFunc outside of outerFunc, then there will be a change to the global $var, but not the outerFunc's local $var. If you added "local" to innerFunc, then outerFunc's $var wouldn't be changed - in essence, there'd be 3 of them:
- $global::var
- $outerFunc::var
- $innerFunc::var
to use Perl's namespace format, sort of.
answered May 11 '16 at 17:16
afbach
662
662
add a comment |Â
add a comment |Â
up vote
1
down vote
You can use a function to force local scope:
sh_local()
eval "$(set)" command eval '"$@"'
Example:
x()
z='new value'
printf 'function x, z = [%s]n' "$z"
y()
z='initial value'
printf 'function y before x, z = [%s]n' "$z"
sh_local x
printf 'function y after x, z = [%s]n' "$z"
printf 'global before y, z = [%s]n' "$z"
y
printf 'global after y, z = [%s]n' "$z"
Result:
global before y, z =
function y before x, z = [initial value]
function x, z = [new value]
function y after x, z = [initial value]
global after y, z = [initial value]
Source
add a comment |Â
up vote
1
down vote
You can use a function to force local scope:
sh_local()
eval "$(set)" command eval '"$@"'
Example:
x()
z='new value'
printf 'function x, z = [%s]n' "$z"
y()
z='initial value'
printf 'function y before x, z = [%s]n' "$z"
sh_local x
printf 'function y after x, z = [%s]n' "$z"
printf 'global before y, z = [%s]n' "$z"
y
printf 'global after y, z = [%s]n' "$z"
Result:
global before y, z =
function y before x, z = [initial value]
function x, z = [new value]
function y after x, z = [initial value]
global after y, z = [initial value]
Source
add a comment |Â
up vote
1
down vote
up vote
1
down vote
You can use a function to force local scope:
sh_local()
eval "$(set)" command eval '"$@"'
Example:
x()
z='new value'
printf 'function x, z = [%s]n' "$z"
y()
z='initial value'
printf 'function y before x, z = [%s]n' "$z"
sh_local x
printf 'function y after x, z = [%s]n' "$z"
printf 'global before y, z = [%s]n' "$z"
y
printf 'global after y, z = [%s]n' "$z"
Result:
global before y, z =
function y before x, z = [initial value]
function x, z = [new value]
function y after x, z = [initial value]
global after y, z = [initial value]
Source
You can use a function to force local scope:
sh_local()
eval "$(set)" command eval '"$@"'
Example:
x()
z='new value'
printf 'function x, z = [%s]n' "$z"
y()
z='initial value'
printf 'function y before x, z = [%s]n' "$z"
sh_local x
printf 'function y after x, z = [%s]n' "$z"
printf 'global before y, z = [%s]n' "$z"
y
printf 'global after y, z = [%s]n' "$z"
Result:
global before y, z =
function y before x, z = [initial value]
function x, z = [new value]
function y after x, z = [initial value]
global after y, z = [initial value]
Source
answered Apr 5 '17 at 22:40
Steven Penny
2,39521635
2,39521635
add a comment |Â
add a comment |Â
up vote
0
down vote
In function innerFunc() the var='new value' wasn't declared as local, therefore it's available in the global scope (once the function has been called).
Conversely, in function outFunc() the local var='initial value' was declared as local, therefore it's not available in the global scope (even if the function has been called).
The implied behavior that's expected in the description could be achieved by declaring local var='new value in function innerFunc().
24.2. Local Variables says all that, too.
As others have stated, this is not a bug in the bash shell. Everything's functioning as it should.
add a comment |Â
up vote
0
down vote
In function innerFunc() the var='new value' wasn't declared as local, therefore it's available in the global scope (once the function has been called).
Conversely, in function outFunc() the local var='initial value' was declared as local, therefore it's not available in the global scope (even if the function has been called).
The implied behavior that's expected in the description could be achieved by declaring local var='new value in function innerFunc().
24.2. Local Variables says all that, too.
As others have stated, this is not a bug in the bash shell. Everything's functioning as it should.
add a comment |Â
up vote
0
down vote
up vote
0
down vote
In function innerFunc() the var='new value' wasn't declared as local, therefore it's available in the global scope (once the function has been called).
Conversely, in function outFunc() the local var='initial value' was declared as local, therefore it's not available in the global scope (even if the function has been called).
The implied behavior that's expected in the description could be achieved by declaring local var='new value in function innerFunc().
24.2. Local Variables says all that, too.
As others have stated, this is not a bug in the bash shell. Everything's functioning as it should.
In function innerFunc() the var='new value' wasn't declared as local, therefore it's available in the global scope (once the function has been called).
Conversely, in function outFunc() the local var='initial value' was declared as local, therefore it's not available in the global scope (even if the function has been called).
The implied behavior that's expected in the description could be achieved by declaring local var='new value in function innerFunc().
24.2. Local Variables says all that, too.
As others have stated, this is not a bug in the bash shell. Everything's functioning as it should.
answered 24 mins ago
Joseph Tingiris
486
486
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f282557%2fscope-of-local-variables-in-shell-functions%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
It is the expected behavior
â fpmurphy1
May 11 '16 at 17:09