Co oznacza podstawienie $ {! Var_name + x}?

10

Znalazłem skrypt, który ma funkcję sprawdzającą, czy zmienna jest ustawiona, ale nie rozumiem jej zbyt dobrze.

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

Co dokładnie dzieje się z tym zastąpieniem?

Karim Manaouil
źródło
powiązane $ {! FOO} i zsh .
αғsнιη

Odpowiedzi:

17

W bashpowłoce ${!var}jest zmienna pośrednia. Rozwija się do wartości zmiennej, której nazwa jest przechowywana $var.

Rozszerzenie zmiennej ${var+value}jest rozszerzeniem POSIX, które rozwija się, valuejeśli zmienna varjest ustawiona (bez względu na to, czy jej wartość jest pusta, czy nie).

Łącząc je, ${!var+x}rozwinie się do, xjeśli ustawiona jest zmienna, której nazwa jest przechowywana $var.

Przykład:

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

(pusty wiersz jako wynik)


Funkcja w pytaniu może zostać skrócona

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

lub nawet:

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

lub nawet:

check_if_variable_is_set()[[ -v $1 ]]

Gdzie -vjest bashtest na nazwę zmiennej, która będzie prawdziwa, jeśli zmienna nazwana jest ustawiona, a false w przeciwnym razie.


POSIXly może być napisany:

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

Zauważ, że wszystkie te są potencjalne podatności na wstrzykiwanie poleceń, jeśli argumentem tej funkcji może być kontrola nad atakującym. Spróbuj na przykład z check_if_variable_is_set 'a[$(id>&2)]'.

Aby temu zapobiec, możesz najpierw sprawdzić, czy argument jest poprawną nazwą zmiennej. Dla zmiennych:

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

(zwróć uwagę, że [[:alpha:]]sprawdzi znaki alfabetu w twoim języku, podczas gdy niektóre powłoki akceptują tylko znaki alfabetu z przenośnego zestawu znaków w swojej zmiennej)

Kusalananda
źródło
Na ziemi nie ma nic bardziej kompletnego niż to. Zasługujesz na to za plik cookie.
Karim Manaouil,
@KarimManaouil Trzeci plik cookie trafia jednak do Stéphane'a :-)
Kusalananda