Проверьте, установлены ли несколько переменных

Я хотел бы убедиться, что в какой-то момент сценария, после source файла конфигурации, установлены несколько переменных, а если нет, то прекратить выполнение, сообщая пользователю о отсутствующей переменной. я пытался

 for var in $one $two $three ; do ... 

но если, например, $two не установлен, цикл никогда не выполняется для $two . Следующее, что я пробовал, было

 for var in one two three ; do if [ -n ${!var} ] ; then echo "$var is set to ${!var}" else echo "$var is not set" fi done 

Но если два не заданы, я все равно получаю «two is set to» вместо «two is not set».

Как я могу убедиться, что все необходимые переменные установлены?

Обновление / решение. Я знаю, что существует разница между «set» и «set, but empty». Теперь я использую (спасибо https://stackoverflow.com/a/16753536/3456281 и ответы на этот вопрос) следующее:

 if [ -n "${!var:-}" ] ; then 

поэтому, если var установлен, но пустой, он по-прежнему считается недействительным.

9 Solutions collect form web for “Проверьте, установлены ли несколько переменных”

Котировка ошибки.

 if [ -n "${!var}" ] ; then 

В будущем: настройка

 set -x 

перед запуском кода вы бы обнаружили проблему. Вместо добавления этого кода вы можете вызвать свой скрипт с помощью

 bash -vx ./my/script.sh 

Единственное, что вам нужно, это цитаты в вашем тесте:

 for var in one two three ; do if [ -n "${!var}" ] ; then echo "$var is set to ${!var}" else echo "$var is not set" fi done 

Работает на меня.

Если вы хотите, чтобы программа остановилась:

 N= ${one?var 1 is unset} ${two:?var 2 is unset or null} ${three:+${N:?var 3 is set and not null}} 

Это будет трюк. Каждое из сообщений, следующих за вопросительным знаком, печатается в stderr а родительская оболочка умирает. Хорошо, хорошо, поэтому не каждое сообщение – только одно – только первое, которое не распечатывает сообщение, заставляет оболочку умирать. Мне нравится использовать эти тесты следующим образом:

 ( for v in "$one" "$two" "$three" ; do i=$((i+1)) ; : ${v:?var $i is unset or null...} done ) || _handle_it 

У меня было гораздо больше, чтобы сказать об этом здесь .

Можете добавить

 set -u 

к началу вашего скрипта, чтобы он прекратил работу, когда он пытается использовать неустановленную переменную.

Сценарий, подобный

 #!/bin/sh set -u echo $foo 

приведет к

script.sh: 3: script.sh: foo: параметр не задан

Если вы используете bash вместо этого, ошибка будет выглядеть так:

script.sh: строка 3: foo: несвязанная переменная

bash 4.2 позволяет проверить, установлена ​​ли переменная с помощью оператора -v ; переменная unset и переменная, установленная в пустую строку, – это два разных условия:

 $ unset foo $ [[ -v foo ]] && echo foo is set $ [[ -z "$foo" ]] && echo foo is empty foo is empty $ foo= $ [[ -v foo ]] && echo foo is set foo is set $ [[ -z "$foo" ]] && echo foo is empty foo is empty 

Я думаю, если вы имеете в виду, что not set , значит, переменная никогда не должна быть инициализирована. Если вы используете [ -n "${!var}" ] , значит, пустая переменная, такая как two="" будет сбой, пока она будет установлена . Вы можете попробовать следующее:

 one=1 three=3 for var in one two three; do declare -p $var > /dev/null 2>&1 \ && printf '%s is set to %s\n' "$var" "${!var}" \ || printf '%s is not set\n' "$var" done 

Решение, которое максимально дружественно, проверяет все требования и сообщает о них вместе, вместо того, чтобы потерпеть неудачу в первом случае и требовать возврата и выхода, чтобы все получилось:

 #!/bin/bash required_vars=(one two three) missing_vars=() for i in "${required_vars[@]}" do test -n "${!i:+y}" || missing_vars+=("$i") done if [ ${#missing_vars[@]} -ne 0 ] then echo "The following variables are not set, but should be:" >&2 printf ' %q\n' "${missing_vars[@]}" >&2 exit 1 fi 

Я использую переменную массива, чтобы отслеживать, какие переменные не были установлены, и использовать результат для составления сообщения, обращенного к пользователю.

Заметки:

  • Я цитировал ${required_vars[@]} в цикле for основном из-за привычки – я бы не советовал включать метасимволы shell в ваши имена переменных!
  • Я не цитировал ${#missing_vars[@]} , потому что это всегда целое число, даже если вы достаточно извращены, чтобы игнорировать предыдущий совет.
  • Я использовал %q при печати; %s обычно будет достаточным.
  • Выход ошибки всегда поступает в поток ошибок с помощью >&2 , поэтому он не попадает в каналы вниз по потоку
  • Тишина – золотая – не печатайте информацию о ходе или отладочную информацию, если она специально не задана. Это делает ошибки более очевидными.

Краткое (хотя и слегка взломанное) решение, чтобы обрабатывать случай, когда для сценария source d установить переменные равным нулю, нужно инициализировать переменные до некоторого специального значения перед поиском сценария, а затем проверить это значение впоследствии, например

 one=#UNSET# two=#UNSET# three=#UNSET# . set_vars_script if [[ $one$two$three == *#UNSET#* ]] ; then echo "One or more essential variables are unset" >&2 exit 1 fi 

Я расширил ответ @ mikeserv .

Эта версия принимает список переменных, чтобы проверить наличие, напечатать имя отсутствующей переменной и вызвать вызов использования () при ошибке.

 REQD_VALUES=("VARIABLE" "FOO" "BAR" "OTHER_VARIABLE") ( i=0; for var_name in ${REQD_VALUES[@]}; do VALUE=${!var_name} ; i=$((i+1)) ; : ${VALUE:?$var_name is missing} done ) || usage 

Пример вывода при отсутствии значения:

 ./myscript.sh: line 42: VALUE: OTHER_VARIABLE is missing 

Обратите внимание, что вы можете изменить переменную VALUE на альтернативное имя, которое лучше подходит для вашего желаемого результата.

  • создайте массив дат в сценариях bash и сопоставьте его текущей дате
  • встроенные условия для назначения
  • Предотвращение или обнаружение действия каталога изменений в сценарии оболочки
  • regexp в ksh для расширений tgz, tar.tgz
  • Переменные в ksh
  • Переименование нескольких каталогов, вставляемых между
  • Использование rename для удаления '.orig' из файла и добавления '_1' в basename
  • Почему это назначение переменной не работает при использовании tee?
  • Заменить текст / строку новой строкой
  • Как передать аргументы скрипту, которые были сгенерированы другим скриптом
  • Как выбрать количество цифр в переменной в моих сценариях?
  • Linux и Unix - лучшая ОС в мире.