Kar*_*uil 10 bash shell-script variable-substitution
我找到了一个脚本,它有一个函数来检查是否设置了变量,但我不太明白。
check_if_variable_is_set() {
var_name=$1
if [ -z "${!var_name+x}" ]; then
false
else
true
fi
}
Run Code Online (Sandbox Code Playgroud)
这个替换到底发生了什么?
Kus*_*nda 17
在bashshell中,${!var}是一个变量间接。它扩展为名称保存在$var.
变量扩展${var+value}是一个 POSIX 扩展,value如果变量var被设置则扩展为(无论其值是否为空)。
结合这些,如果设置了名称保留的变量,${!var+x}则将扩展为。x$var
例子:
$ foo=hello
$ var=foo
Run Code Online (Sandbox Code Playgroud)
$ echo "${!var+$var is set, its value is ${!var}}"
foo is set, its value is hello
Run Code Online (Sandbox Code Playgroud)
$ unset foo
$ echo "${!var+$var is set, its value is ${!var}}"
Run Code Online (Sandbox Code Playgroud)
(空行作为输出)
问题中的功能可以缩短为
check_if_variable_is_set () { [ -n "${!1+x}" ]; }
Run Code Online (Sandbox Code Playgroud)
甚至:
check_if_variable_is_set () { [ -v "$1" ]; }
Run Code Online (Sandbox Code Playgroud)
甚至:
check_if_variable_is_set()[[ -v $1 ]]
Run Code Online (Sandbox Code Playgroud)
哪里-v是bash对变量名称的测试,如果设置了命名变量,则为真,否则为假。
POSIXly,它可以写成:
check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }
Run Code Online (Sandbox Code Playgroud)
请注意,如果该函数的参数最终可能受到攻击者的控制,那么所有这些都是潜在的命令注入漏洞。尝试例如使用check_if_variable_is_set 'a[$(id>&2)]'.
为了防止这种情况,您可能需要先验证参数是否是有效的变量名。对于变量:
check_if_variable_is_set() {
case $1 in
("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
(*) eval '[ -n "${'"$1"'+x}" ]'
esac
}
Run Code Online (Sandbox Code Playgroud)
(请注意,[[:alpha:]]将检查您的语言环境中的字母字符,而某些 shell 仅接受来自其变量中可移植字符集的字母字符)