No bash
shell, ${!var}
é uma variável indireta. Ele se expande para o valor da variável cujo nome é mantido $var
.
A expansão da variável ${var+value}
é uma expansão POSIX que se expande para value
se a variável var
estiver configurada (independentemente de seu valor estar vazio ou não).
Combinando isso, ${!var+x}
seria expandido para x
se a variável cujo nome é mantido $var
estiver definida.
Exemplo:
$ 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}}"
(linha vazia como saída)
A função na pergunta pode ser reduzida para
check_if_variable_is_set () { [ -n "${!1+x}" ]; }
ou até:
check_if_variable_is_set () { [ -v "$1" ]; }
ou até:
check_if_variable_is_set()[[ -v $1 ]]
Onde -v
está um bash
teste em um nome de variável que será verdadeiro se a variável nomeada estiver configurada e false caso contrário.
POSIX, poderia ser escrito:
check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }
Observe que todas essas são vulnerabilidades em potencial de injeção de comando se o argumento para essa função puder acabar sob o controle de um invasor. Tente, por exemplo, com check_if_variable_is_set 'a[$(id>&2)]'
.
Para evitar isso, convém verificar se o argumento é um nome de variável válido primeiro. Para variáveis:
check_if_variable_is_set() {
case $1 in
("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
(*) eval '[ -n "${'"$1"'+x}" ]'
esac
}
(observe que [[:alpha:]]
irá procurar caracteres alfabéticos em seu local, enquanto alguns shells aceitam apenas caracteres alfabéticos do conjunto de caracteres portáteis em suas variáveis)