Расширение параметра
Очевидный ответ - использовать одну из специальных форм расширения параметров:
: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}
Или лучше (см. Раздел «Положение двойных кавычек» ниже):
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
Первый вариант (с использованием только ?
) требует установки STATE, но STATE = "" (пустая строка) в порядке & mdash; не совсем то, что вы хотите, но альтернативные и старые обозначения.
Второй вариант (с использованием :?
) требует, чтобы DEST был установлен и не был пустым.
Если вы не укажете сообщение, оболочка предоставит сообщение по умолчанию.
Конструкция ${var?}
переносима обратно в Версию 7 UNIX и Bourne Shell (1978 или около того). Конструкция ${var:?}
немного новее: я думаю, что она была в System III UNIX примерно в 1981 году, но до этого она могла быть в PWB UNIX. Поэтому он находится в оболочке Korn и в оболочках POSIX, включая, в частности, Bash.
Обычно это документируется на справочной странице оболочки в разделе под названием Расширение параметров . Например, руководство bash
гласит:
${parameter:?word}
Ошибка дисплея, если ноль или не установлен. Если параметр равен нулю или не задан, расширение слова (или сообщение на этот счет, если слово отсутствует) записывается со стандартной ошибкой, и оболочка, если она не является интерактивной, завершается. В противном случае значение параметра подставляется.
Колонное командование
Вероятно, мне следует добавить, что команда двоеточия просто оценивает свои аргументы и затем успешно завершается. Это оригинальная запись комментария оболочки (до '#
' до конца строки). Долгое время сценарии оболочки Bourne имели двоеточие в качестве первого символа. Оболочка C будет читать сценарий и использовать первый символ, чтобы определить, относится ли он к оболочке C (хеш '1034 *') или к оболочке Борна (двоеточие :
). Затем ядро приняло участие и добавило поддержку #!/path/to/program
, а оболочка Bourne получила комментарии #
, и соглашение о двоеточии ушло на второй план. Но если вы столкнетесь со сценарием, начинающимся с двоеточия, теперь вы поймете, почему.
Положение двойных кавычек
blong спросил в комментарии :
Есть мысли по этому поводу? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
Суть обсуждения:
… Однако, когда я shellcheck
это (с версией 0.4.1), я получаю это сообщение:
In script.sh line 13:
: ${FOO:?"The environment variable 'FOO' must be set and non-empty"}
^-- SC2086: Double quote to prevent globbing and word splitting.
Любой совет, что мне делать в этом случае?
Краткий ответ: «делай как shellcheck
предлагает»:
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
Чтобы проиллюстрировать почему, изучите следующее. Обратите внимание, что команда :
не отображает свои аргументы (но оболочка действительно оценивает аргументы). Мы хотим видеть аргументы, поэтому код ниже использует printf "%s\n"
вместо :
.
$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$
$ x="*"
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
bash: x: You must set x
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
*
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$
Обратите внимание, как значение в $x
расширяется до сначала *
, а затем списка имен файлов, когда общее выражение не в двойных кавычках. Это то, что рекомендует shellcheck
, должно быть исправлено. Я не проверял, что он не возражает против формы, в которой выражение заключено в двойные кавычки, но разумно предположить, что все будет в порядке.