В bash
оболочке ${!var}
есть переменная косвенность. Он расширяется до значения переменной, имя которой хранится в $var
.
Расширение переменной ${var+value}
- это расширение POSIX, которое расширяется, value
если переменная var
установлена (независимо от того, является ли ее значение пустым или нет).
Комбинируя их, ${!var+x}
можно расширить, x
если переменная, имя которой хранится, $var
установлена.
Пример:
$ 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}}"
(пустая строка в качестве вывода)
Функция в вопросе может быть сокращена до
check_if_variable_is_set () { [ -n "${!1+x}" ]; }
или даже:
check_if_variable_is_set () { [ -v "$1" ]; }
или даже:
check_if_variable_is_set()[[ -v $1 ]]
Где -v
это bash
испытание на имя переменной , которая будет верно , если названная переменная установлена, и ложь в противном случае.
POSIXly, это может быть написано:
check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }
Обратите внимание, что все это потенциальные уязвимости при внедрении команд, если аргумент этой функции может оказаться под контролем злоумышленника. Попробуйте, например, с check_if_variable_is_set 'a[$(id>&2)]'
.
Чтобы избежать этого, вы можете сначала проверить, что аргумент является допустимым именем переменной. Для переменных:
check_if_variable_is_set() {
case $1 in
("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
(*) eval '[ -n "${'"$1"'+x}" ]'
esac
}
(обратите внимание, что в вашей локали[[:alpha:]]
будет проверяться наличие буквенных символов, в то время как некоторые оболочки принимают только буквенные символы из переносимого набора символов в их переменной)