shell functions and variables with the same name
From Bash Manual:
Note that shell functions and variables with the same name may result in multiple identically-named entries in the environment
passed to the shell’s children. Care should be taken in cases where
this may cause a problem.
How can bash distinguish "shell functions and variables with the
same name" ?
$ func () { return 3; }; func=4; declare -p func; declare -f func;
declare -- func="4"
func ()
{
return 3
}
When does "multiple identically-named entries in the environment
passed to the shell’s children" happen?
What "care" should be taken for what problem?
bash environment-variables function
add a comment |
From Bash Manual:
Note that shell functions and variables with the same name may result in multiple identically-named entries in the environment
passed to the shell’s children. Care should be taken in cases where
this may cause a problem.
How can bash distinguish "shell functions and variables with the
same name" ?
$ func () { return 3; }; func=4; declare -p func; declare -f func;
declare -- func="4"
func ()
{
return 3
}
When does "multiple identically-named entries in the environment
passed to the shell’s children" happen?
What "care" should be taken for what problem?
bash environment-variables function
add a comment |
From Bash Manual:
Note that shell functions and variables with the same name may result in multiple identically-named entries in the environment
passed to the shell’s children. Care should be taken in cases where
this may cause a problem.
How can bash distinguish "shell functions and variables with the
same name" ?
$ func () { return 3; }; func=4; declare -p func; declare -f func;
declare -- func="4"
func ()
{
return 3
}
When does "multiple identically-named entries in the environment
passed to the shell’s children" happen?
What "care" should be taken for what problem?
bash environment-variables function
From Bash Manual:
Note that shell functions and variables with the same name may result in multiple identically-named entries in the environment
passed to the shell’s children. Care should be taken in cases where
this may cause a problem.
How can bash distinguish "shell functions and variables with the
same name" ?
$ func () { return 3; }; func=4; declare -p func; declare -f func;
declare -- func="4"
func ()
{
return 3
}
When does "multiple identically-named entries in the environment
passed to the shell’s children" happen?
What "care" should be taken for what problem?
bash environment-variables function
bash environment-variables function
edited Mar 5 at 22:28
codeforester
380317
380317
asked Jul 30 '17 at 0:41
TimTim
28.3k78269490
28.3k78269490
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
The general story: separate namespaces
Generally shells distinguish between variables and functions because they're used in different contexts. In a nutshell, a name is a variable name if it appears after a $
, or as an argument to builtins such as export
(without -f
) and unset
(without -f
). A name is a function name if it appears as a command (after alias expansion) or as an argument to export -f
, unset -f
, etc.
Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too).
With older bash: confusion due to function export
Bash, unlike most other shells, can also export functions to the environment. Since there's no type indication in the environment, there's no way to recognize whether an entry in the environment is a function or not, other than by analyzing the name or the value of the environment variable.
Older versions of bash stored a function in the environment using the function's name as the name, and something that looks like the function definition as the function's value. For example:
bash-4.1$ foobar () { echo foobar; }
bash-4.1$ export -f foobar
bash-4.1$ env |grep -A1 foobar
foobar=() { echo foobar
}
bash-4.1$
Note that there's no way to distinguish a function whose code is { echo foobar; }
from a variable whose value is () { echo foobar}
(where 
is a newline character). This turned out to be a bad design decision.
Sometimes shell scripts get invoked with environment variables whose value is under control of a potentially hostile entity. CGI scripts, for example. Bash's function export/import feature allowed injecting functions that way. For example executing the script
#!/bin/bash
ls
from a remote request is safe as long as the environment doesn't contain variables with a certain name (such as PATH
). But if the request can set the environment variable ls
to () { cat /etc/passwd; }
then bash would happily execute cat /etc/passwd
since that's the body of the ls
function.
With newer bash: confusion mostly alleviated
This security vulnerability was discovered by Stéphane Chazelas as one of the aspects of the Shellshock bug. In post-Shellshock versions of bash, exported functions are identified by their name rather than by their content.
bash-4.3$ foobar () { echo foobar; }
bash-4.3$ export -f foobar
bash-4.3$ env |grep -A1 foobar
BASH_FUNC_foobar%%=() { echo foobar
}
There is no security issue now because names like BASH_FUNC_foobar%%
are not commonly used as command names, and can be filtered out by interfaces that allow passing environment variables. It's technically possible to have a %
character in the name of an environment variable (that's what makes modern bash's exported functions work), but normally people don't do this because shells don't accept %
in the name of a variable.
The sentence in the bash manual refers to the old (pre-Shellshock) behavior. It should be updated or removed. With modern bash versions, there is no ambiguity in the environment if you assume that environment variables won't have a name ending in %%
.
@Tim Holy bold overflow! You really need to learn a full paragraph where half the text isn't bolded.
– Gilles
Aug 5 '17 at 10:59
"Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too)." When a shell variable is exported to the environment, is it only to assign the export attribute of the shell variable, and the shell variable and its corresponding environment variable are the same object instead of different copies? By "the name of the environment variable is the same as the shell variable (and the values are the same too)", do you mean the shell variable and its corresponding environment variable are separate copies?
– Tim
Aug 5 '17 at 11:06
I really think that my reorganization of your reply make it more readable to me.
– Tim
Aug 5 '17 at 11:08
add a comment |
A similar thing happens in Emacs Lisp. It has two namespaces, one for functions and one for variables. If you dereference a symbol in function context ((var)
) it will call the function, if you defreference it in variable context (var
i.e. without the brackets) it will give you the variable. For example:
(defun myvar (myvar)
"adds 3 to MYVAR"
(+ 3 myvar))
(setq myvar 7)
(message (myvar myvar))
Will execute the function myvar
with the argument 7
which is the dereference of the variable myvar
.
This can become very confusing if you are not used to it.
After looking at your question and making the tests for bash I'm surprised that it presents the same behaviour. Translating the ELisp from above into bash:
[grochmal@phoenix ~]$ myvar () { echo $(($1+3)); }
[grochmal@phoenix ~]$ myvar=7
[grochmal@phoenix ~]$ myvar $myvar
10
Bash is a little less confusing in this than ELisp because you need the $
to mark the variable. Still, this may look like a declare
of a single name containing two things. See:
[grochmal@phoenix ~]$ declare -p myvar
declare -x myvar="7"
[grochmal@phoenix ~]$ declare -f myvar
myvar ()
{
echo $(($1+3))
}
(P.S. Once you get used to the existence of two namespaces, e.g. you program in ELisp for a while, this stops becoming confusing)
1
You've completely missed the case the manual refers to, which is when variables are communicated through the environment. In all fairness, that case no longer applies to modern versions of bash (post-Shellshock), which encode functions differently. But even so the reference to Lisp is hard to follow even for people who are familiar with Lisp. It would be much better to explain this in an autonomous way.
– Gilles
Jul 30 '17 at 22:54
@Gilles - It is not that I missed it, I simply did not know it :) . I missed that part of Shellshock altogether and then attempted to test this on a post-shellshock bash only. I actually need to thank you for clearing that up.
– grochmal
Jul 31 '17 at 9:41
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f382660%2fshell-functions-and-variables-with-the-same-name%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The general story: separate namespaces
Generally shells distinguish between variables and functions because they're used in different contexts. In a nutshell, a name is a variable name if it appears after a $
, or as an argument to builtins such as export
(without -f
) and unset
(without -f
). A name is a function name if it appears as a command (after alias expansion) or as an argument to export -f
, unset -f
, etc.
Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too).
With older bash: confusion due to function export
Bash, unlike most other shells, can also export functions to the environment. Since there's no type indication in the environment, there's no way to recognize whether an entry in the environment is a function or not, other than by analyzing the name or the value of the environment variable.
Older versions of bash stored a function in the environment using the function's name as the name, and something that looks like the function definition as the function's value. For example:
bash-4.1$ foobar () { echo foobar; }
bash-4.1$ export -f foobar
bash-4.1$ env |grep -A1 foobar
foobar=() { echo foobar
}
bash-4.1$
Note that there's no way to distinguish a function whose code is { echo foobar; }
from a variable whose value is () { echo foobar}
(where 
is a newline character). This turned out to be a bad design decision.
Sometimes shell scripts get invoked with environment variables whose value is under control of a potentially hostile entity. CGI scripts, for example. Bash's function export/import feature allowed injecting functions that way. For example executing the script
#!/bin/bash
ls
from a remote request is safe as long as the environment doesn't contain variables with a certain name (such as PATH
). But if the request can set the environment variable ls
to () { cat /etc/passwd; }
then bash would happily execute cat /etc/passwd
since that's the body of the ls
function.
With newer bash: confusion mostly alleviated
This security vulnerability was discovered by Stéphane Chazelas as one of the aspects of the Shellshock bug. In post-Shellshock versions of bash, exported functions are identified by their name rather than by their content.
bash-4.3$ foobar () { echo foobar; }
bash-4.3$ export -f foobar
bash-4.3$ env |grep -A1 foobar
BASH_FUNC_foobar%%=() { echo foobar
}
There is no security issue now because names like BASH_FUNC_foobar%%
are not commonly used as command names, and can be filtered out by interfaces that allow passing environment variables. It's technically possible to have a %
character in the name of an environment variable (that's what makes modern bash's exported functions work), but normally people don't do this because shells don't accept %
in the name of a variable.
The sentence in the bash manual refers to the old (pre-Shellshock) behavior. It should be updated or removed. With modern bash versions, there is no ambiguity in the environment if you assume that environment variables won't have a name ending in %%
.
@Tim Holy bold overflow! You really need to learn a full paragraph where half the text isn't bolded.
– Gilles
Aug 5 '17 at 10:59
"Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too)." When a shell variable is exported to the environment, is it only to assign the export attribute of the shell variable, and the shell variable and its corresponding environment variable are the same object instead of different copies? By "the name of the environment variable is the same as the shell variable (and the values are the same too)", do you mean the shell variable and its corresponding environment variable are separate copies?
– Tim
Aug 5 '17 at 11:06
I really think that my reorganization of your reply make it more readable to me.
– Tim
Aug 5 '17 at 11:08
add a comment |
The general story: separate namespaces
Generally shells distinguish between variables and functions because they're used in different contexts. In a nutshell, a name is a variable name if it appears after a $
, or as an argument to builtins such as export
(without -f
) and unset
(without -f
). A name is a function name if it appears as a command (after alias expansion) or as an argument to export -f
, unset -f
, etc.
Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too).
With older bash: confusion due to function export
Bash, unlike most other shells, can also export functions to the environment. Since there's no type indication in the environment, there's no way to recognize whether an entry in the environment is a function or not, other than by analyzing the name or the value of the environment variable.
Older versions of bash stored a function in the environment using the function's name as the name, and something that looks like the function definition as the function's value. For example:
bash-4.1$ foobar () { echo foobar; }
bash-4.1$ export -f foobar
bash-4.1$ env |grep -A1 foobar
foobar=() { echo foobar
}
bash-4.1$
Note that there's no way to distinguish a function whose code is { echo foobar; }
from a variable whose value is () { echo foobar}
(where 
is a newline character). This turned out to be a bad design decision.
Sometimes shell scripts get invoked with environment variables whose value is under control of a potentially hostile entity. CGI scripts, for example. Bash's function export/import feature allowed injecting functions that way. For example executing the script
#!/bin/bash
ls
from a remote request is safe as long as the environment doesn't contain variables with a certain name (such as PATH
). But if the request can set the environment variable ls
to () { cat /etc/passwd; }
then bash would happily execute cat /etc/passwd
since that's the body of the ls
function.
With newer bash: confusion mostly alleviated
This security vulnerability was discovered by Stéphane Chazelas as one of the aspects of the Shellshock bug. In post-Shellshock versions of bash, exported functions are identified by their name rather than by their content.
bash-4.3$ foobar () { echo foobar; }
bash-4.3$ export -f foobar
bash-4.3$ env |grep -A1 foobar
BASH_FUNC_foobar%%=() { echo foobar
}
There is no security issue now because names like BASH_FUNC_foobar%%
are not commonly used as command names, and can be filtered out by interfaces that allow passing environment variables. It's technically possible to have a %
character in the name of an environment variable (that's what makes modern bash's exported functions work), but normally people don't do this because shells don't accept %
in the name of a variable.
The sentence in the bash manual refers to the old (pre-Shellshock) behavior. It should be updated or removed. With modern bash versions, there is no ambiguity in the environment if you assume that environment variables won't have a name ending in %%
.
@Tim Holy bold overflow! You really need to learn a full paragraph where half the text isn't bolded.
– Gilles
Aug 5 '17 at 10:59
"Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too)." When a shell variable is exported to the environment, is it only to assign the export attribute of the shell variable, and the shell variable and its corresponding environment variable are the same object instead of different copies? By "the name of the environment variable is the same as the shell variable (and the values are the same too)", do you mean the shell variable and its corresponding environment variable are separate copies?
– Tim
Aug 5 '17 at 11:06
I really think that my reorganization of your reply make it more readable to me.
– Tim
Aug 5 '17 at 11:08
add a comment |
The general story: separate namespaces
Generally shells distinguish between variables and functions because they're used in different contexts. In a nutshell, a name is a variable name if it appears after a $
, or as an argument to builtins such as export
(without -f
) and unset
(without -f
). A name is a function name if it appears as a command (after alias expansion) or as an argument to export -f
, unset -f
, etc.
Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too).
With older bash: confusion due to function export
Bash, unlike most other shells, can also export functions to the environment. Since there's no type indication in the environment, there's no way to recognize whether an entry in the environment is a function or not, other than by analyzing the name or the value of the environment variable.
Older versions of bash stored a function in the environment using the function's name as the name, and something that looks like the function definition as the function's value. For example:
bash-4.1$ foobar () { echo foobar; }
bash-4.1$ export -f foobar
bash-4.1$ env |grep -A1 foobar
foobar=() { echo foobar
}
bash-4.1$
Note that there's no way to distinguish a function whose code is { echo foobar; }
from a variable whose value is () { echo foobar}
(where 
is a newline character). This turned out to be a bad design decision.
Sometimes shell scripts get invoked with environment variables whose value is under control of a potentially hostile entity. CGI scripts, for example. Bash's function export/import feature allowed injecting functions that way. For example executing the script
#!/bin/bash
ls
from a remote request is safe as long as the environment doesn't contain variables with a certain name (such as PATH
). But if the request can set the environment variable ls
to () { cat /etc/passwd; }
then bash would happily execute cat /etc/passwd
since that's the body of the ls
function.
With newer bash: confusion mostly alleviated
This security vulnerability was discovered by Stéphane Chazelas as one of the aspects of the Shellshock bug. In post-Shellshock versions of bash, exported functions are identified by their name rather than by their content.
bash-4.3$ foobar () { echo foobar; }
bash-4.3$ export -f foobar
bash-4.3$ env |grep -A1 foobar
BASH_FUNC_foobar%%=() { echo foobar
}
There is no security issue now because names like BASH_FUNC_foobar%%
are not commonly used as command names, and can be filtered out by interfaces that allow passing environment variables. It's technically possible to have a %
character in the name of an environment variable (that's what makes modern bash's exported functions work), but normally people don't do this because shells don't accept %
in the name of a variable.
The sentence in the bash manual refers to the old (pre-Shellshock) behavior. It should be updated or removed. With modern bash versions, there is no ambiguity in the environment if you assume that environment variables won't have a name ending in %%
.
The general story: separate namespaces
Generally shells distinguish between variables and functions because they're used in different contexts. In a nutshell, a name is a variable name if it appears after a $
, or as an argument to builtins such as export
(without -f
) and unset
(without -f
). A name is a function name if it appears as a command (after alias expansion) or as an argument to export -f
, unset -f
, etc.
Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too).
With older bash: confusion due to function export
Bash, unlike most other shells, can also export functions to the environment. Since there's no type indication in the environment, there's no way to recognize whether an entry in the environment is a function or not, other than by analyzing the name or the value of the environment variable.
Older versions of bash stored a function in the environment using the function's name as the name, and something that looks like the function definition as the function's value. For example:
bash-4.1$ foobar () { echo foobar; }
bash-4.1$ export -f foobar
bash-4.1$ env |grep -A1 foobar
foobar=() { echo foobar
}
bash-4.1$
Note that there's no way to distinguish a function whose code is { echo foobar; }
from a variable whose value is () { echo foobar}
(where 
is a newline character). This turned out to be a bad design decision.
Sometimes shell scripts get invoked with environment variables whose value is under control of a potentially hostile entity. CGI scripts, for example. Bash's function export/import feature allowed injecting functions that way. For example executing the script
#!/bin/bash
ls
from a remote request is safe as long as the environment doesn't contain variables with a certain name (such as PATH
). But if the request can set the environment variable ls
to () { cat /etc/passwd; }
then bash would happily execute cat /etc/passwd
since that's the body of the ls
function.
With newer bash: confusion mostly alleviated
This security vulnerability was discovered by Stéphane Chazelas as one of the aspects of the Shellshock bug. In post-Shellshock versions of bash, exported functions are identified by their name rather than by their content.
bash-4.3$ foobar () { echo foobar; }
bash-4.3$ export -f foobar
bash-4.3$ env |grep -A1 foobar
BASH_FUNC_foobar%%=() { echo foobar
}
There is no security issue now because names like BASH_FUNC_foobar%%
are not commonly used as command names, and can be filtered out by interfaces that allow passing environment variables. It's technically possible to have a %
character in the name of an environment variable (that's what makes modern bash's exported functions work), but normally people don't do this because shells don't accept %
in the name of a variable.
The sentence in the bash manual refers to the old (pre-Shellshock) behavior. It should be updated or removed. With modern bash versions, there is no ambiguity in the environment if you assume that environment variables won't have a name ending in %%
.
edited Aug 5 '17 at 10:58
answered Jul 31 '17 at 0:37
GillesGilles
545k12811071622
545k12811071622
@Tim Holy bold overflow! You really need to learn a full paragraph where half the text isn't bolded.
– Gilles
Aug 5 '17 at 10:59
"Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too)." When a shell variable is exported to the environment, is it only to assign the export attribute of the shell variable, and the shell variable and its corresponding environment variable are the same object instead of different copies? By "the name of the environment variable is the same as the shell variable (and the values are the same too)", do you mean the shell variable and its corresponding environment variable are separate copies?
– Tim
Aug 5 '17 at 11:06
I really think that my reorganization of your reply make it more readable to me.
– Tim
Aug 5 '17 at 11:08
add a comment |
@Tim Holy bold overflow! You really need to learn a full paragraph where half the text isn't bolded.
– Gilles
Aug 5 '17 at 10:59
"Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too)." When a shell variable is exported to the environment, is it only to assign the export attribute of the shell variable, and the shell variable and its corresponding environment variable are the same object instead of different copies? By "the name of the environment variable is the same as the shell variable (and the values are the same too)", do you mean the shell variable and its corresponding environment variable are separate copies?
– Tim
Aug 5 '17 at 11:06
I really think that my reorganization of your reply make it more readable to me.
– Tim
Aug 5 '17 at 11:08
@Tim Holy bold overflow! You really need to learn a full paragraph where half the text isn't bolded.
– Gilles
Aug 5 '17 at 10:59
@Tim Holy bold overflow! You really need to learn a full paragraph where half the text isn't bolded.
– Gilles
Aug 5 '17 at 10:59
"Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too)." When a shell variable is exported to the environment, is it only to assign the export attribute of the shell variable, and the shell variable and its corresponding environment variable are the same object instead of different copies? By "the name of the environment variable is the same as the shell variable (and the values are the same too)", do you mean the shell variable and its corresponding environment variable are separate copies?
– Tim
Aug 5 '17 at 11:06
"Variables can be exported to the environment. The name of the environment variable is the same as the shell variable (and the values are the same too)." When a shell variable is exported to the environment, is it only to assign the export attribute of the shell variable, and the shell variable and its corresponding environment variable are the same object instead of different copies? By "the name of the environment variable is the same as the shell variable (and the values are the same too)", do you mean the shell variable and its corresponding environment variable are separate copies?
– Tim
Aug 5 '17 at 11:06
I really think that my reorganization of your reply make it more readable to me.
– Tim
Aug 5 '17 at 11:08
I really think that my reorganization of your reply make it more readable to me.
– Tim
Aug 5 '17 at 11:08
add a comment |
A similar thing happens in Emacs Lisp. It has two namespaces, one for functions and one for variables. If you dereference a symbol in function context ((var)
) it will call the function, if you defreference it in variable context (var
i.e. without the brackets) it will give you the variable. For example:
(defun myvar (myvar)
"adds 3 to MYVAR"
(+ 3 myvar))
(setq myvar 7)
(message (myvar myvar))
Will execute the function myvar
with the argument 7
which is the dereference of the variable myvar
.
This can become very confusing if you are not used to it.
After looking at your question and making the tests for bash I'm surprised that it presents the same behaviour. Translating the ELisp from above into bash:
[grochmal@phoenix ~]$ myvar () { echo $(($1+3)); }
[grochmal@phoenix ~]$ myvar=7
[grochmal@phoenix ~]$ myvar $myvar
10
Bash is a little less confusing in this than ELisp because you need the $
to mark the variable. Still, this may look like a declare
of a single name containing two things. See:
[grochmal@phoenix ~]$ declare -p myvar
declare -x myvar="7"
[grochmal@phoenix ~]$ declare -f myvar
myvar ()
{
echo $(($1+3))
}
(P.S. Once you get used to the existence of two namespaces, e.g. you program in ELisp for a while, this stops becoming confusing)
1
You've completely missed the case the manual refers to, which is when variables are communicated through the environment. In all fairness, that case no longer applies to modern versions of bash (post-Shellshock), which encode functions differently. But even so the reference to Lisp is hard to follow even for people who are familiar with Lisp. It would be much better to explain this in an autonomous way.
– Gilles
Jul 30 '17 at 22:54
@Gilles - It is not that I missed it, I simply did not know it :) . I missed that part of Shellshock altogether and then attempted to test this on a post-shellshock bash only. I actually need to thank you for clearing that up.
– grochmal
Jul 31 '17 at 9:41
add a comment |
A similar thing happens in Emacs Lisp. It has two namespaces, one for functions and one for variables. If you dereference a symbol in function context ((var)
) it will call the function, if you defreference it in variable context (var
i.e. without the brackets) it will give you the variable. For example:
(defun myvar (myvar)
"adds 3 to MYVAR"
(+ 3 myvar))
(setq myvar 7)
(message (myvar myvar))
Will execute the function myvar
with the argument 7
which is the dereference of the variable myvar
.
This can become very confusing if you are not used to it.
After looking at your question and making the tests for bash I'm surprised that it presents the same behaviour. Translating the ELisp from above into bash:
[grochmal@phoenix ~]$ myvar () { echo $(($1+3)); }
[grochmal@phoenix ~]$ myvar=7
[grochmal@phoenix ~]$ myvar $myvar
10
Bash is a little less confusing in this than ELisp because you need the $
to mark the variable. Still, this may look like a declare
of a single name containing two things. See:
[grochmal@phoenix ~]$ declare -p myvar
declare -x myvar="7"
[grochmal@phoenix ~]$ declare -f myvar
myvar ()
{
echo $(($1+3))
}
(P.S. Once you get used to the existence of two namespaces, e.g. you program in ELisp for a while, this stops becoming confusing)
1
You've completely missed the case the manual refers to, which is when variables are communicated through the environment. In all fairness, that case no longer applies to modern versions of bash (post-Shellshock), which encode functions differently. But even so the reference to Lisp is hard to follow even for people who are familiar with Lisp. It would be much better to explain this in an autonomous way.
– Gilles
Jul 30 '17 at 22:54
@Gilles - It is not that I missed it, I simply did not know it :) . I missed that part of Shellshock altogether and then attempted to test this on a post-shellshock bash only. I actually need to thank you for clearing that up.
– grochmal
Jul 31 '17 at 9:41
add a comment |
A similar thing happens in Emacs Lisp. It has two namespaces, one for functions and one for variables. If you dereference a symbol in function context ((var)
) it will call the function, if you defreference it in variable context (var
i.e. without the brackets) it will give you the variable. For example:
(defun myvar (myvar)
"adds 3 to MYVAR"
(+ 3 myvar))
(setq myvar 7)
(message (myvar myvar))
Will execute the function myvar
with the argument 7
which is the dereference of the variable myvar
.
This can become very confusing if you are not used to it.
After looking at your question and making the tests for bash I'm surprised that it presents the same behaviour. Translating the ELisp from above into bash:
[grochmal@phoenix ~]$ myvar () { echo $(($1+3)); }
[grochmal@phoenix ~]$ myvar=7
[grochmal@phoenix ~]$ myvar $myvar
10
Bash is a little less confusing in this than ELisp because you need the $
to mark the variable. Still, this may look like a declare
of a single name containing two things. See:
[grochmal@phoenix ~]$ declare -p myvar
declare -x myvar="7"
[grochmal@phoenix ~]$ declare -f myvar
myvar ()
{
echo $(($1+3))
}
(P.S. Once you get used to the existence of two namespaces, e.g. you program in ELisp for a while, this stops becoming confusing)
A similar thing happens in Emacs Lisp. It has two namespaces, one for functions and one for variables. If you dereference a symbol in function context ((var)
) it will call the function, if you defreference it in variable context (var
i.e. without the brackets) it will give you the variable. For example:
(defun myvar (myvar)
"adds 3 to MYVAR"
(+ 3 myvar))
(setq myvar 7)
(message (myvar myvar))
Will execute the function myvar
with the argument 7
which is the dereference of the variable myvar
.
This can become very confusing if you are not used to it.
After looking at your question and making the tests for bash I'm surprised that it presents the same behaviour. Translating the ELisp from above into bash:
[grochmal@phoenix ~]$ myvar () { echo $(($1+3)); }
[grochmal@phoenix ~]$ myvar=7
[grochmal@phoenix ~]$ myvar $myvar
10
Bash is a little less confusing in this than ELisp because you need the $
to mark the variable. Still, this may look like a declare
of a single name containing two things. See:
[grochmal@phoenix ~]$ declare -p myvar
declare -x myvar="7"
[grochmal@phoenix ~]$ declare -f myvar
myvar ()
{
echo $(($1+3))
}
(P.S. Once you get used to the existence of two namespaces, e.g. you program in ELisp for a while, this stops becoming confusing)
answered Jul 30 '17 at 1:26
grochmalgrochmal
5,92131647
5,92131647
1
You've completely missed the case the manual refers to, which is when variables are communicated through the environment. In all fairness, that case no longer applies to modern versions of bash (post-Shellshock), which encode functions differently. But even so the reference to Lisp is hard to follow even for people who are familiar with Lisp. It would be much better to explain this in an autonomous way.
– Gilles
Jul 30 '17 at 22:54
@Gilles - It is not that I missed it, I simply did not know it :) . I missed that part of Shellshock altogether and then attempted to test this on a post-shellshock bash only. I actually need to thank you for clearing that up.
– grochmal
Jul 31 '17 at 9:41
add a comment |
1
You've completely missed the case the manual refers to, which is when variables are communicated through the environment. In all fairness, that case no longer applies to modern versions of bash (post-Shellshock), which encode functions differently. But even so the reference to Lisp is hard to follow even for people who are familiar with Lisp. It would be much better to explain this in an autonomous way.
– Gilles
Jul 30 '17 at 22:54
@Gilles - It is not that I missed it, I simply did not know it :) . I missed that part of Shellshock altogether and then attempted to test this on a post-shellshock bash only. I actually need to thank you for clearing that up.
– grochmal
Jul 31 '17 at 9:41
1
1
You've completely missed the case the manual refers to, which is when variables are communicated through the environment. In all fairness, that case no longer applies to modern versions of bash (post-Shellshock), which encode functions differently. But even so the reference to Lisp is hard to follow even for people who are familiar with Lisp. It would be much better to explain this in an autonomous way.
– Gilles
Jul 30 '17 at 22:54
You've completely missed the case the manual refers to, which is when variables are communicated through the environment. In all fairness, that case no longer applies to modern versions of bash (post-Shellshock), which encode functions differently. But even so the reference to Lisp is hard to follow even for people who are familiar with Lisp. It would be much better to explain this in an autonomous way.
– Gilles
Jul 30 '17 at 22:54
@Gilles - It is not that I missed it, I simply did not know it :) . I missed that part of Shellshock altogether and then attempted to test this on a post-shellshock bash only. I actually need to thank you for clearing that up.
– grochmal
Jul 31 '17 at 9:41
@Gilles - It is not that I missed it, I simply did not know it :) . I missed that part of Shellshock altogether and then attempted to test this on a post-shellshock bash only. I actually need to thank you for clearing that up.
– grochmal
Jul 31 '17 at 9:41
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f382660%2fshell-functions-and-variables-with-the-same-name%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
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
Required, but never shown
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
Required, but never shown
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
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown