W bash
powł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ę, value
jeśli zmienna var
jest ustawiona (bez względu na to, czy jej wartość jest pusta, czy nie).
Łącząc je, ${!var+x}
rozwinie się do, x
jeś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 -v
jest bash
test 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)