在bash
外壳中,${!var}
是一个变量间接寻址。它扩展为名称保留在中的变量的值$var
。
变量扩展${var+value}
是POSIX扩展,value
如果var
设置了变量,则扩展为POSIX扩展(无论其值是否为空)。
结合这些,${!var+x}
将扩展为x
是否$var
设置了保留名称的变量。
例:
$ 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}}"
(空行作为输出)
问题中的功能可以简化为
check_if_variable_is_set () { [ -n "${!1+x}" ]; }
甚至:
check_if_variable_is_set () { [ -v "$1" ]; }
甚至:
check_if_variable_is_set()[[ -v $1 ]]
对变量名-v
的bash
测试在哪里,如果设置了命名变量,则为true,否则为false。
POSIXly,可以这样写:
check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }
请注意,如果该函数的参数最终可能受到攻击者的控制,则所有这些都是潜在的命令注入漏洞。例如,尝试使用check_if_variable_is_set 'a[$(id>&2)]'
。
为避免这种情况,您可能需要首先验证该参数是否为有效的变量名。对于变量:
check_if_variable_is_set() {
case $1 in
("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
(*) eval '[ -n "${'"$1"'+x}" ]'
esac
}
(请注意,这[[:alpha:]]
将在您的语言环境中检查字母字符,而某些外壳仅接受其变量中的可移植字符集中的字母字符)