What does the substitution ${!var_name+x} mean?
I found a script that has a function that checks if a variable is set but i don't understand it very well.
check_if_variable_is_set() {
var_name=$1
if [ -z "${!var_name+x}" ]; then
false
else
true
fi
}
What exactly happens with this substitution ?
bash shell-script variable-substitution
add a comment |
I found a script that has a function that checks if a variable is set but i don't understand it very well.
check_if_variable_is_set() {
var_name=$1
if [ -z "${!var_name+x}" ]; then
false
else
true
fi
}
What exactly happens with this substitution ?
bash shell-script variable-substitution
related ${!FOO} and zsh.
– αғsнιη
Feb 18 at 15:01
add a comment |
I found a script that has a function that checks if a variable is set but i don't understand it very well.
check_if_variable_is_set() {
var_name=$1
if [ -z "${!var_name+x}" ]; then
false
else
true
fi
}
What exactly happens with this substitution ?
bash shell-script variable-substitution
I found a script that has a function that checks if a variable is set but i don't understand it very well.
check_if_variable_is_set() {
var_name=$1
if [ -z "${!var_name+x}" ]; then
false
else
true
fi
}
What exactly happens with this substitution ?
bash shell-script variable-substitution
bash shell-script variable-substitution
asked Feb 18 at 14:27
Karim ManaouilKarim Manaouil
216110
216110
related ${!FOO} and zsh.
– αғsнιη
Feb 18 at 15:01
add a comment |
related ${!FOO} and zsh.
– αғsнιη
Feb 18 at 15:01
related ${!FOO} and zsh.
– αғsнιη
Feb 18 at 15:01
related ${!FOO} and zsh.
– αғsнιη
Feb 18 at 15:01
add a comment |
1 Answer
1
active
oldest
votes
In the bash
shell, ${!var}
is a variable indirection. It expands to the value of the variable whose name is kept in $var
.
The variable expansion ${var+value}
is a POSIX expansion that expands to value
if the variable var
is set (no matter if its value is empty or not).
Combining these, ${!var+x}
would expand to x
if the variable whose name is kept in $var
is set.
Example:
$ foo=hello
$ var=foo
$ echo "${!var+$var is set, its value is ${!var}}"
foo is set, its value is hello
$ unset foo
$ echo "${!var+$var is set, its value is ${!var}}"
(empty line as output)
The function in the question could be shortened to
check_if_variable_is_set () { [ -n "${!1+x}" ]; }
or even:
check_if_variable_is_set () { [ -v "$1" ]; }
or even:
check_if_variable_is_set()[[ -v $1 ]]
Where -v
is a bash
test on a variable name which will be true if the named variable is set, and false otherwise.
POSIXly, it could be written:
check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }
Note that all those are potential command injection vulnerabilities if the argument to that function could end up being under control of an attacker. Try for instance with check_if_variable_is_set 'a[$(id>&2)]'
.
To guard against that, you may want to verify that the argument is a valid variable name first. For variables:
check_if_variable_is_set() {
case $1 in
("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
(*) eval '[ -n "${'"$1"'+x}" ]'
esac
}
(note that [[:alpha:]]
will check for alphabetical characters in your locale while some shells only accept alphabetical characters from the portable character set in their variable)
There is nothing on earth more complete than this. You deserve a cookie for that.
– Karim Manaouil
Feb 18 at 16:47
@KarimManaouil A third of that cookie goes to Stéphane though :-)
– Kusalananda
Feb 18 at 17:35
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%2f501368%2fwhat-does-the-substitution-var-namex-mean%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
In the bash
shell, ${!var}
is a variable indirection. It expands to the value of the variable whose name is kept in $var
.
The variable expansion ${var+value}
is a POSIX expansion that expands to value
if the variable var
is set (no matter if its value is empty or not).
Combining these, ${!var+x}
would expand to x
if the variable whose name is kept in $var
is set.
Example:
$ foo=hello
$ var=foo
$ echo "${!var+$var is set, its value is ${!var}}"
foo is set, its value is hello
$ unset foo
$ echo "${!var+$var is set, its value is ${!var}}"
(empty line as output)
The function in the question could be shortened to
check_if_variable_is_set () { [ -n "${!1+x}" ]; }
or even:
check_if_variable_is_set () { [ -v "$1" ]; }
or even:
check_if_variable_is_set()[[ -v $1 ]]
Where -v
is a bash
test on a variable name which will be true if the named variable is set, and false otherwise.
POSIXly, it could be written:
check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }
Note that all those are potential command injection vulnerabilities if the argument to that function could end up being under control of an attacker. Try for instance with check_if_variable_is_set 'a[$(id>&2)]'
.
To guard against that, you may want to verify that the argument is a valid variable name first. For variables:
check_if_variable_is_set() {
case $1 in
("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
(*) eval '[ -n "${'"$1"'+x}" ]'
esac
}
(note that [[:alpha:]]
will check for alphabetical characters in your locale while some shells only accept alphabetical characters from the portable character set in their variable)
There is nothing on earth more complete than this. You deserve a cookie for that.
– Karim Manaouil
Feb 18 at 16:47
@KarimManaouil A third of that cookie goes to Stéphane though :-)
– Kusalananda
Feb 18 at 17:35
add a comment |
In the bash
shell, ${!var}
is a variable indirection. It expands to the value of the variable whose name is kept in $var
.
The variable expansion ${var+value}
is a POSIX expansion that expands to value
if the variable var
is set (no matter if its value is empty or not).
Combining these, ${!var+x}
would expand to x
if the variable whose name is kept in $var
is set.
Example:
$ foo=hello
$ var=foo
$ echo "${!var+$var is set, its value is ${!var}}"
foo is set, its value is hello
$ unset foo
$ echo "${!var+$var is set, its value is ${!var}}"
(empty line as output)
The function in the question could be shortened to
check_if_variable_is_set () { [ -n "${!1+x}" ]; }
or even:
check_if_variable_is_set () { [ -v "$1" ]; }
or even:
check_if_variable_is_set()[[ -v $1 ]]
Where -v
is a bash
test on a variable name which will be true if the named variable is set, and false otherwise.
POSIXly, it could be written:
check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }
Note that all those are potential command injection vulnerabilities if the argument to that function could end up being under control of an attacker. Try for instance with check_if_variable_is_set 'a[$(id>&2)]'
.
To guard against that, you may want to verify that the argument is a valid variable name first. For variables:
check_if_variable_is_set() {
case $1 in
("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
(*) eval '[ -n "${'"$1"'+x}" ]'
esac
}
(note that [[:alpha:]]
will check for alphabetical characters in your locale while some shells only accept alphabetical characters from the portable character set in their variable)
There is nothing on earth more complete than this. You deserve a cookie for that.
– Karim Manaouil
Feb 18 at 16:47
@KarimManaouil A third of that cookie goes to Stéphane though :-)
– Kusalananda
Feb 18 at 17:35
add a comment |
In the bash
shell, ${!var}
is a variable indirection. It expands to the value of the variable whose name is kept in $var
.
The variable expansion ${var+value}
is a POSIX expansion that expands to value
if the variable var
is set (no matter if its value is empty or not).
Combining these, ${!var+x}
would expand to x
if the variable whose name is kept in $var
is set.
Example:
$ foo=hello
$ var=foo
$ echo "${!var+$var is set, its value is ${!var}}"
foo is set, its value is hello
$ unset foo
$ echo "${!var+$var is set, its value is ${!var}}"
(empty line as output)
The function in the question could be shortened to
check_if_variable_is_set () { [ -n "${!1+x}" ]; }
or even:
check_if_variable_is_set () { [ -v "$1" ]; }
or even:
check_if_variable_is_set()[[ -v $1 ]]
Where -v
is a bash
test on a variable name which will be true if the named variable is set, and false otherwise.
POSIXly, it could be written:
check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }
Note that all those are potential command injection vulnerabilities if the argument to that function could end up being under control of an attacker. Try for instance with check_if_variable_is_set 'a[$(id>&2)]'
.
To guard against that, you may want to verify that the argument is a valid variable name first. For variables:
check_if_variable_is_set() {
case $1 in
("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
(*) eval '[ -n "${'"$1"'+x}" ]'
esac
}
(note that [[:alpha:]]
will check for alphabetical characters in your locale while some shells only accept alphabetical characters from the portable character set in their variable)
In the bash
shell, ${!var}
is a variable indirection. It expands to the value of the variable whose name is kept in $var
.
The variable expansion ${var+value}
is a POSIX expansion that expands to value
if the variable var
is set (no matter if its value is empty or not).
Combining these, ${!var+x}
would expand to x
if the variable whose name is kept in $var
is set.
Example:
$ foo=hello
$ var=foo
$ echo "${!var+$var is set, its value is ${!var}}"
foo is set, its value is hello
$ unset foo
$ echo "${!var+$var is set, its value is ${!var}}"
(empty line as output)
The function in the question could be shortened to
check_if_variable_is_set () { [ -n "${!1+x}" ]; }
or even:
check_if_variable_is_set () { [ -v "$1" ]; }
or even:
check_if_variable_is_set()[[ -v $1 ]]
Where -v
is a bash
test on a variable name which will be true if the named variable is set, and false otherwise.
POSIXly, it could be written:
check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }
Note that all those are potential command injection vulnerabilities if the argument to that function could end up being under control of an attacker. Try for instance with check_if_variable_is_set 'a[$(id>&2)]'
.
To guard against that, you may want to verify that the argument is a valid variable name first. For variables:
check_if_variable_is_set() {
case $1 in
("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
(*) eval '[ -n "${'"$1"'+x}" ]'
esac
}
(note that [[:alpha:]]
will check for alphabetical characters in your locale while some shells only accept alphabetical characters from the portable character set in their variable)
edited Feb 18 at 15:51
Stéphane Chazelas
307k57581937
307k57581937
answered Feb 18 at 14:30
KusalanandaKusalananda
132k17252416
132k17252416
There is nothing on earth more complete than this. You deserve a cookie for that.
– Karim Manaouil
Feb 18 at 16:47
@KarimManaouil A third of that cookie goes to Stéphane though :-)
– Kusalananda
Feb 18 at 17:35
add a comment |
There is nothing on earth more complete than this. You deserve a cookie for that.
– Karim Manaouil
Feb 18 at 16:47
@KarimManaouil A third of that cookie goes to Stéphane though :-)
– Kusalananda
Feb 18 at 17:35
There is nothing on earth more complete than this. You deserve a cookie for that.
– Karim Manaouil
Feb 18 at 16:47
There is nothing on earth more complete than this. You deserve a cookie for that.
– Karim Manaouil
Feb 18 at 16:47
@KarimManaouil A third of that cookie goes to Stéphane though :-)
– Kusalananda
Feb 18 at 17:35
@KarimManaouil A third of that cookie goes to Stéphane though :-)
– Kusalananda
Feb 18 at 17:35
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%2f501368%2fwhat-does-the-substitution-var-namex-mean%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
related ${!FOO} and zsh.
– αғsнιη
Feb 18 at 15:01