Que signifie la substitution $ {! Var_name + x}?

10

J'ai trouvé un script qui a une fonction qui vérifie si une variable est définie mais je ne la comprends pas très bien.

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

Que se passe-t-il exactement avec cette substitution?

Karim Manaouil
la source
$ {! FOO} et zsh liés .
αғsнιη

Réponses:

17

Dans le bashshell, ${!var}est une indirection variable. Il se développe à la valeur de la variable dont le nom est conservé $var.

L'expansion de variable ${var+value}est une extension POSIX qui se développe valuesi la variable varest définie (que sa valeur soit vide ou non).

La combinaison de ces derniers ${!var+x}se développerait xsi la variable dont le nom est conservé $varest définie.

Exemple:

$ 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}}"

(ligne vide en sortie)


La fonction dans la question pourrait être réduite à

check_if_variable_is_set () { [ -n "${!1+x}" ]; }

ou même:

check_if_variable_is_set () { [ -v "$1" ]; }

ou même:

check_if_variable_is_set()[[ -v $1 ]]

-vest un bashtest sur un nom de variable qui sera vrai si la variable nommée est définie, et faux sinon.


POSIX, il pourrait s'écrire:

check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }

Notez que ce sont toutes des vulnérabilités potentielles d'injection de commandes si l'argument de cette fonction pourrait finir par être sous le contrôle d'un attaquant. Essayez par exemple avec check_if_variable_is_set 'a[$(id>&2)]'.

Pour éviter cela, vous pouvez d'abord vérifier que l'argument est un nom de variable valide. Pour les variables:

check_if_variable_is_set() {
  case $1 in
    ("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
    (*)  eval '[ -n "${'"$1"'+x}" ]'
  esac
}

(notez que [[:alpha:]]cela vérifiera les caractères alphabétiques dans votre région tandis que certains shells n'acceptent que les caractères alphabétiques du jeu de caractères portable dans leur variable)

Kusalananda
la source
Il n'y a rien de plus complet sur terre que cela. Vous méritez un cookie pour cela.
Karim Manaouil
@KarimManaouil Un tiers de ce cookie va cependant à Stéphane :-)
Kusalananda