Bash. Тест для переменной unset, используя функцию
Простой тест переменной Bash:
${varName:? "${varName} is not defined"}
Я хотел бы повторно использовать это, поставив его в функцию.
Как понравиться?
Не удалось выполнить
#
# Test a variable exists
tvar(){
val=${1:? "${1} must be defined, preferably in $basedir"}
if [ -z ${val} ]
then
echo Zero length value
else
echo ${1} exists, value ${1}
fi
}
т.е. Мне нужно выйти, если тест не удался.
Ответы
Ответ 1
Благодаря ответу lhunath's я попал на страницу Bash man
, которую я пропустил сотни раз:
When not performing substring expansion, bash tests for a parameter that
is unset or null; omitting the colon results in a test only for a parame‐
ter that is unset.
Это побудило меня создать следующую таблицу истинности:
| unset | set | set and | meaning
| | but null | not null |
============+=======+==========+==========+=============================
${var-_} | T | F | T | not null or not set
------------+-------+----------+----------+-----------------------------
${var:-_} | T | T | T | always true, use for subst.
------------+-------+----------+----------+-----------------------------
$var | F | F | T | var is set and not null
------------+-------+----------+----------+-----------------------------
${!var[@]} | F | T | T | var is set
В этой таблице представлена спецификация в последней строке. На странице Bash man
говорится: "Если имя не является массивом, оно расширяется до 0, если имя задано и в противном случае -" null ". Для целей этой таблицы истинности она ведет себя одинаково, даже если это массив.
Ответ 2
То, что вы ищете, является косвенным.
assertNotEmpty() {
: "${!1:? "$1 is empty, aborting."}"
}
Это приводит к тому, что script прерывается с сообщением об ошибке, если вы выполните что-то вроде этого:
$ foo=""
$ assertNotEmpty foo
bash: !1: foo is empty, aborting.
Если вы просто хотите проверить, является ли foo
пустым, вместо прерывания script используйте это вместо функции:
[[ $foo ]]
Например:
until read -p "What is your name? " name && [[ $name ]]; do
echo "You didn't enter your name. Please, try again." >&2
done
Также обратите внимание, что существует очень важная разница между параметрами empty и unset. Вы должны позаботиться о том, чтобы не смущать эти условия! Пустым параметром является тот, который установлен, но просто установлен на пустую строку. Параметр unset - это тот, который вообще не существует.
В предыдущих примерах все проверяются на параметры empty. Если вы хотите проверить параметры unset и считать все заданные параметры ОК, независимо от того, пустые они или нет, используйте это:
[[ ! $foo && ${foo-_} ]]
Используйте его в такой функции:
assertIsSet() {
[[ ! ${!1} && ${!1-_} ]] && {
echo "$1 is not set, aborting." >&2
exit 1
}
}
Который только прервет script, когда имя параметра, которое вы передаете, обозначает параметр, который не установлен:
$ ( foo="blah"; assertIsSet foo; echo "Still running." )
Still running.
$ ( foo=""; assertIsSet foo; echo "Still running." )
Still running.
$ ( unset foo; assertIsSet foo; echo "Still running." )
foo is not set, aborting.
Ответ 3
Вы хотите использовать [ -z ${parameter+word} ]
Некоторая часть man bash
:
Parameter Expansion
...
In each of the cases below, word is subject to tilde expansion, parameter expansion, command substitution, and
arithmetic expansion. When not performing substring expansion, bash tests for a parameter that is unset or null;
omitting the colon results in a test only for a parameter that is unset.
...
${parameter:+word}
Use Alternate Value. If parameter is null or unset, nothing is substituted, otherwise the expansion of
word is substituted.
...
Другими словами:
${parameter+word}
Use Alternate Value. If parameter is unset, nothing is substituted, otherwise the expansion of
word is substituted.
несколько примеров:
$ set | grep FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$ declare FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=1
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ unset FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$
Ответ 4
Эта функция проверяет переменные, которые ARE CURRENTLY установлены. Переменная может быть даже массивом. Обратите внимание, что в bash: 0 == TRUE, 1 == FALSE.
function var.defined {
eval '[[ ${!'$1'[@]} ]]'
}
# Typical Usage of var.defined {}
declare you="Your Name Here" ref='you';
read -p "What your name: " you;
if var.defined you; then # Simple demo using literal text
echo "BASH recognizes $you";
echo "BASH also knows a reference to $ref as ${!ref}, by indirection.";
fi
unset you # have just been killed by a master :D
if ! var.defined $ref; then # Standard demo using an expanded literal value
echo "BASH doesn't know $ref any longer";
fi
read -s -N 1 -p "Press any key to continue...";
echo "";
Итак, чтобы быть понятным здесь, функция проверяет литерал. Каждый раз, когда команда вызывается в bash, переменные GENERALLY "сбрасываются" или "заменяются" базовым значением, если только:
- $varRef ($):\$varRef
- $varRef - одинарная кавычка '$ varRef'
Ответ 5
Я точно не понял, что вам нужно. Я пытаюсь ответить вам, несмотря на это.
т.е. Мне нужно выйти, если тест не удался.
Код:
${varName:? "${varName} is not defined"}
вернет ненулевой код выхода, если нет переменной с именем "varName". Код завершения последней команды сохраняется в $?
.
О вашем коде:
val=${1:? "${1} must be defined, preferably in $basedir"}
Возможно, он не делает то, что вам нужно. В случае, если $1
не определен, "${1}"
не будет заменен ничем. Вероятно, вы хотите использовать одинарные кавычки, которые буквально записывают ${1}
без подстановки.
val=${1:? '${1} must be defined, preferably in $basedir'
Ответ 6
Не уверен, что это именно то, что вы хотите, но удобный трюк, который я использую при написании нового + комплекса script, - это использовать "set -o"
set -o # будет делать бомбу script, когда находит неустановленную переменную
EG:
$grep '$ 1' chex.sh
случай "$ 1" в
$./chex.sh
./chex.sh: строка 111: $1: несвязанная переменная
$./chex.sh foo
неверно/без параметров прошло. Выход из
Ответ 7
if set | grep -q '^VARIABLE='
then
echo VARIABLE is set
fi