O que significa a substituição $ {! Var_name + x}?


10

Eu encontrei um script que tem uma função que verifica se uma variável está definida, mas eu não a entendo muito bem.

check_if_variable_is_set() {
    var_name=$1
    if [ -z "${!var_name+x}" ]; then
        false
    else
        true
    fi
}

O que exatamente acontece com essa substituição?


relacionados a $ {! FOO} e zsh .
18719

Respostas:


17

No bashshell, ${!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 valuese a variável varestiver configurada (independentemente de seu valor estar vazio ou não).

Combinando isso, ${!var+x}seria expandido para xse a variável cujo nome é mantido $varestiver 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 -vestá um bashteste 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)


Não há nada na terra mais completo que isso. Você merece um cookie por isso.
Karim Manaouil

@KarimManaouil Um terço desse cookie vai para Stéphane :-)
Kusalananda
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.