if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi,
Дженс
211
Примечание для тех, кто ищет решения: Есть много высоко оцененных ответов на этот вопрос, которые отвечают на вопрос «переменная непустая». Более корректирующие решения («набор переменных») упомянуты в ответах Дженса и Лайонела ниже.
Натан Кидд
8
Рассел Хармон и Симус также правы в своем -vтесте, хотя, по-видимому, он доступен только в новых версиях bashи не переносится между оболочками.
Грэм,
5
Как указывает @NathanKidd, правильные решения дают Лайонел и Йенс. prosseek, вы должны переключить свой принятый ответ на один из них.
Гарретт
3
... или неправильный ответ может быть отвергнут более проницательным среди нас, так как @prosseek не решает проблему.
dan3
Ответы:
2305
(Обычно) правильный путь
if[-z ${var+x}];then echo "var is unset";else echo "var is set to '$var'";fi
где ${var+x}является расширением параметра , который оценивает ничего , если varне установлено, и заменяет строку в xпротивном случае.
Цитаты Отступление
Кавычки могут быть опущены (так что мы можем сказать ${var+x}вместо "${var+x}"), потому что этот синтаксис и использование гарантирует, что это будет расширяться только до чего-то, что не требует кавычек (так как оно расширяется до x(которое не содержит разрывов слов, поэтому не нуждается в кавычках), или до ничего (что приводит к тому [ -z ], что удобно вычислять до того же значения (true), что [ -z "" ]и так)).
Однако, хотя кавычки могут быть безопасно опущены, и это было не сразу очевидно для всех (даже для первого автора этого объяснения кавычек, который также является основным кодировщиком Bash), иногда было бы лучше написать решение с кавычками как [ -z "${var+x}" ], при очень маленькой возможной стоимости штрафа за скорость O (1). Первый автор также добавил это в качестве комментария рядом с кодом, использующим это решение, предоставив URL-адрес для этого ответа, который теперь также включает в себя объяснение того, почему цитаты можно безопасно опускать.
(Часто) Неправильный путь
if[-z "$var"];then echo "var is blank";else echo "var is set to '$var'";fi
Это часто неправильно, поскольку не различает переменную, которая не установлена, и переменную, для которой задана пустая строка. То есть, если var='', тогда вышеприведенное решение выведет "var is blank".
Различие между unset и «set to empty string» является существенным в ситуациях, когда пользователь должен указать расширение или дополнительный список свойств, и если не указывать их, по умолчанию используется непустое значение, тогда как указание пустой строки должно заставить скрипт использовать пустое расширение или список дополнительных свойств.
Различие не может быть существенным в каждом сценарии все же. В тех случаях [ -z "$var" ]будет просто отлично.
@Garrett, ваше изменение сделало этот ответ неверным, ${var+x}это правильная замена для использования. Использование [ -z ${var:+x} ]дает не отличный результат, чем [ -z "$var" ].
Грэм,
11
Это не работает Я получаю «not set» независимо от того, установлено ли значение var или нет (очищается с помощью «unset var», «echo $ var» не выводит).
Brent212
10
Для синтаксиса решения $ {параметр + слово} раздел официального руководства - gnu.org/software/bash/manual/… ; однако, ошибка в том, что он не очень четко упоминает этот синтаксис, а говорит просто кавычка (пропуск двоеточия [":"] приводит к проверке только для неустановленного параметра. .. $ {параметр: + слово} [означает] Если параметр равен нулю или не установлен, ничто не подставляется, в противном случае подставляется расширение слова.); цитируемая ссылка pubs.opengroup.org/onlinepubs/9699919799/utilities/… (полезно знать) содержит гораздо более четкие документы.
Архитектор Судьбы
7
Похоже, кавычки необходимы, когда вы используете несколько выражений, например, [ -z "" -a -z ${var+x} ]получает bash: [: argument expectedв bash 4.3-ubuntu (но не, например, zsh). Мне действительно не нравится ответ с использованием синтаксиса, который в некоторых случаях срабатывает.
FauxFaux
41
Использование простого [ -z $var ]не более «неправильно», чем пропуск кавычек. В любом случае, вы делаете предположения о своем вкладе. Если вы хорошо относитесь к пустой строке как к неустановленной, [ -z $var ]это все, что вам нужно.
nshew
910
Для проверки ненулевой / ненулевой строковой переменной, т.е. если она установлена, используйте
if[-n "$1"]
Это противоположность -z. Я использую -nбольше, чем -z.
Вы бы использовали это как:
if[-n "$1"];then
echo "You supplied the first parameter!"else
echo "First parameter not supplied."fi
Я обычно предпочитаю [[ ]]более [ ], а [[ ]]более мощный и вызывает меньше проблем в определенных ситуациях (см этот вопрос для объяснения разницы между ними). Вопрос специально требует решения для bash и не содержит никаких требований по переносимости.
поток
18
Вопрос заключается в том, как можно увидеть , если переменная установлена . Тогда вы не можете предположить , что переменная будет установлена.
Здравствуйте, до свидания,
7
Я согласен, []работает лучше, особенно для сценариев оболочки (не Bash).
Hengjie
73
Сбой на set -u.
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
63
Обратите внимание, что -nэто тест по умолчанию, так что проще [ "$1" ]или лучше [[ $1 ]]работать. Также обратите внимание, что с [[ ]]цитированием нет необходимости .
TNE
479
Вот как проверить, является ли параметр не установленным , пустым («Null») или установленным со значением :
+--------------------+----------------------+-----------------+-----------------+|Expression| parameter | parameter | parameter ||in script:|Set and NotNull|SetButNull|Unset|+--------------------+----------------------+-----------------+-----------------+| ${parameter:-word}| substitute parameter | substitute word | substitute word || ${parameter-word}| substitute parameter | substitute null | substitute word || ${parameter:=word}| substitute parameter | assign word | assign word || ${parameter=word}| substitute parameter | substitute null | assign word || ${parameter:?word}| substitute parameter | error, exit | error, exit || ${parameter?word}| substitute parameter | substitute null | error, exit || ${parameter:+word}| substitute word | substitute null | substitute null || ${parameter+word}| substitute word | substitute word | substitute null |+--------------------+----------------------+-----------------+-----------------+
Во всех случаях, показанных с «заменой», выражение заменяется показанным значением. Во всех случаях, показанных с помощью «assign», параметру присваивается это значение, которое также заменяет выражение.
Чтобы показать это в действии:
+--------------------+----------------------+-----------------+-----------------+|Expression| FOO="world"| FOO=""| unset FOO ||in script:|(Set and NotNull)|(SetButNull)|(Unset)|+--------------------+----------------------+-----------------+-----------------+| ${FOO:-hello}| world | hello | hello || ${FOO-hello}| world |""| hello || ${FOO:=hello}| world | FOO=hello | FOO=hello || ${FOO=hello}| world |""| FOO=hello || ${FOO:?hello}| world | error, exit | error, exit || ${FOO?hello}| world |""| error, exit || ${FOO:+hello}| hello |""|""|| ${FOO+hello}| hello | hello |""|+--------------------+----------------------+-----------------+-----------------+
@HelloGoodbye Да, это работает: set foo; echo ${1:-set but null or unset}echos "foo"; set --; echo ${1:-set but null or unset}отголоски установлены, но ноль ...
Jens
4
@HelloGoodbye Позиционные параметры могут быть установлены с помощью set:-)
Jens
95
Этот ответ очень запутанный. Есть практические примеры того, как использовать эту таблицу?
Бен Дэвис
12
@BenDavis Подробности объясняются в ссылке на стандарт POSIX, который ссылается на главу, из которой взята таблица. Одна конструкция, которую я использую практически в любом сценарии, который я пишу, - : ${FOOBAR:=/etc/foobar.conf}это установить значение по умолчанию для переменной, если она не установлена или равна нулю.
Йенс
1
parameterлюбое имя переменной. wordявляется некоторой строкой, которую нужно заменить, в зависимости от того, какой синтаксис в таблице вы используете, и от того, установлена ли переменная $parameter, установлена ли она на ноль или не установлена. Не для того, чтобы сделать вещи более сложными, но wordтакже может включать переменные! Это может быть очень полезно для передачи необязательных аргументов, разделенных символом. Например: ${parameter:+,${parameter}}выводит запятую, ,$parameterесли она установлена, но не равна нулю. В данном случае wordэто,${parameter}
TrinitronX
260
Хотя большинство методов, изложенных здесь, верны, bash 4.2 поддерживает фактический тест на наличие переменной ( man bash ), а не тестирует значение переменной.
Примечательно, что этот подход не вызовет ошибки при использовании для проверки неустановленной переменной в set -u/ set -o nounsetmode, в отличие от многих других подходов, таких как использование [ -z.
В bash 4.1.2, независимо от того, установлена ли переменная, [[ -v aaa ]]; echo $?==>-bash: conditional binary operator expected-bash: syntax error near 'aaa'
Дан
32
Аргумент '-v' для встроенной команды 'test' был добавлен в bash 4.2.
Ti Strga
19
аргумент -v был добавлен в качестве дополнения к опции оболочки -u (существительное). При включенном 'nounset' (set -u) оболочка вернет ошибку и завершит работу, если она не является интерактивной. $ # был хорош для проверки позиционных параметров. Тем не менее, именованные переменные нуждались в каком-то ином способе, кроме сгущения, для идентификации их как неустановленных. К сожалению, эта функция появилась слишком поздно, потому что многие обязаны быть совместимыми с более ранними версиями, и в этом случае они не могут ее использовать. Единственный другой вариант - использовать трюки или «хаки», чтобы обойти это, как показано выше, но это наиболее не элегантно.
osirisgothra
2
Обратите внимание, что это не работает для переменных, которые объявлены, но не установлены. напр.declare -a foo
miken32
17
Вот почему я продолжаю читать после принятого / получившего наибольшее количество голосов ответа.
Джо
176
Есть много способов сделать это, одним из которых является следующее:
Существует разница между неустановленным параметром и параметром с нулевым значением.
chepner
21
Я просто хочу быть педантичным и указать, что это противоположный ответ на вопрос. Вопросы спрашивают, установлена ли переменная, а не установлена ли переменная.
Philluminati
47
[[ ]]это не что иное, как ловушка переносимости. if [ -n "$1" ]следует использовать здесь.
Дженс
73
Этот ответ неверен. Вопрос спрашивает, как определить, установлена ли переменная, а не установлено ли для нее непустое значение. Данный foo="", $fooимеет значение, но -zпросто сообщит, что он пуст. И -z $fooвзорвется, если у вас есть set -o nounset.
Кит Томпсон,
4
Это зависит от определения «переменная установлена». Если вы хотите проверить, установлена ли переменная в ненулевую строку, то ответ mbranning будет правильным. Но если вы хотите проверить, объявлена ли переменная, но не инициализирована (то есть foo=), тогда ответ Рассела верен.
поток
77
Я всегда нахожу таблицу POSIX в другом ответе медлительной, поэтому вот мое мнение:
Обратите внимание, что каждая группа (с и без предшествующего двоеточия) имеет одинаковый набор и неустановленные наблюдения , поэтому отличается только то, как обрабатываются пустые случаи.
С предыдущим двоеточием пустой и неустановленный регистры идентичны, поэтому я бы использовал те, где это возможно (т. Е. Используйте :=, а не только =потому, что пустой регистр несовместим).
Рубрики:
набор средств VARIABLEне пусто ( VARIABLE="something")
empty означает VARIABLEпусто / null ( VARIABLE="")
неустановленное средство VARIABLEне существует ( unset VARIABLE)
Ценности:
$VARIABLE означает, что результатом является исходное значение переменной.
"default" означает, что результатом была предоставленная строка замены.
"" означает, что результат равен нулю (пустая строка).
exit 127 означает, что скрипт прекращает выполнение с кодом завершения 127.
$(VARIABLE="default")означает, что результатом является исходное значение переменной, и предоставленная строка замены назначается переменной для будущего использования.
Вы исправили только те, которые являются реальными ошибками кодирования (случаи нежелательной косвенности при работе с переменными). Я сделал правку, чтобы исправить еще несколько случаев, когда доллар имеет значение при интерпретации описания. Кстати, все переменные оболочки (за исключением массивов) являются строковыми переменными; может случиться так, что они содержат строку, которую можно интерпретировать как число. Разговор о струнах только затуманивает сообщение. Кавычки не имеют ничего общего со строками, они просто альтернатива экранированию. VARIABLE=""может быть написано как VARIABLE=. Тем не менее, первый более читабелен.
Палек
Спасибо за таблицу, это очень полезно, однако я пытаюсь завершить работу скрипта, если он не установлен или пуст. Но код выхода - 1, а не 127.
Астронавт
64
Чтобы увидеть, является ли переменная непустой, я использую
if[[ $var ]];then...# `$var' expands to a nonempty string
Противоположные тесты, если переменная не установлена или пуста:
if[[! $var ]];then...# `$var' expands to the empty string (set or not)
Чтобы увидеть, установлена ли переменная (пустая или непустая), я использую
if[[ ${var+x}]];then...# `var' exists (empty or nonempty)if[[ ${1+x}]];then...# Parameter 1 exists (empty or nonempty)
Противоположные тесты, если переменная не установлена:
if[[! ${var+x}]];then...# `var' is not set at allif[[! ${1+x}]];then...# We were called with no arguments
Я тоже использовал это некоторое время; просто в сокращенном виде:[ $isMac ] && param="--enable-shared"
@Bhaskar Я думаю, это потому, что этот ответ уже предоставил практически тот же ответ (использовать, ${variable+x}чтобы получить, xесли $variableон установлен) почти полгода назад. Также в нем есть гораздо более подробное объяснение, почему это правильно.
Марк Хаферкамп
но ${variable+x}менее
читабелен
35
В современной версии Bash (4.2 или более поздней версии, я думаю, я точно не знаю) я бы попробовал это:
if[!-v SOMEVARIABLE ]#note the lack of a $ sigilthen
echo "Variable is unset"elif[-z "$SOMEVARIABLE"]then
echo "Variable is set to an empty string"else
echo "Variable is set to some string"fi
Также обратите внимание, что [ -v "$VARNAME" ]это не так, но просто выполняет другой тест. Предположим VARNAME=foo; Затем он проверяет, установлена ли переменная с именем foo.
Чепнер
5
Примечание для тех, кто хочет переносимости, -vне совместим с POSIX
kzh
Если кто-то получает [: -v: unexpected operator, он должен использовать bashвместо sh.
Коппор
25
if["$1"!=""];then
echo \$1 is setelse
echo \$1 is not setfi
Хотя для аргументов обычно лучше всего проверить $ #, что, по моему мнению, является количеством аргументов.
if[ $# -gt 0 ]; then
echo \$1 is setelse
echo \$1 is not setfi
Первый тест задом наперед; Я думаю, что вы хотите [ "$1" != "" ](или [ -n "$1" ]) ...
Гордон Дэвиссон
10
Это не удастся, если $1задана пустая строка.
Здравствуйте, до свидания
2
Вторая часть ответа (подсчет параметров) - полезный обходной путь для первой части ответа, которая не работает, если $1для нее задана пустая строка.
Марк Берри
Это не удастся, если включен set -o nounset.
Флим
21
Запись
Я даю сильно сфокусированный на Bash ответ из-за bashтега.
Короткий ответ
Пока вы имеете дело только с именованными переменными в Bash, эта функция всегда должна сообщать вам, установлена ли переменная, даже если это пустой массив.
variable-is-set(){
declare -p "$1"&>/dev/null
}
Почему это работает
В Bash (по крайней мере, начиная с версии 3.0), если varпеременная объявлена / установлена, declare -p varвыводит declareкоманду, которая установит переменную varв соответствии с ее текущим типом и значением, и возвращает код состояния 0(успех). Если значение varне объявлено, declare -p varвыводится сообщение об ошибке stderrи возвращается код состояния 1. Используя &>/dev/null, перенаправляет как обычный, так stdoutи stderrвыходной /dev/null, никогда не будет видно и без изменения кода состояния. Таким образом, функция возвращает только код состояния.
Почему другие методы (иногда) терпят неудачу в Bash
[ -n "$var" ]: Только проверяет, если ${var[0]}не пусто. (В Bash так $varже, как ${var[0]}.)
[ -n "${var+x}" ]: Это только проверяет, если ${var[0]}установлено.
[ "${#var[@]}" != 0 ]: Это только проверяет, установлен ли хотя бы один индекс $var.
Когда этот метод не работает в Bash
Это работает только для именованных переменных ( в том числе $_), а не некоторых специальных переменных ( $!, $@, $#, $$, $*, $?, $-, $0, $1, $2, ..., и любой я забыл). Поскольку ни один из них не является массивом, стиль POSIX [ -n "${var+x}" ]работает для всех этих специальных переменных. Но остерегайтесь оборачивать его в функцию, так как многие специальные переменные изменяют значения / существование при вызове функций.
Примечание о совместимости оболочки
Если в вашем скрипте есть массивы и вы пытаетесь сделать его совместимым с как можно большим количеством оболочек, рассмотрите возможность использования typeset -pвместо declare -p. Я читал, что ksh поддерживает только первое, но не смог проверить это. Я знаю, что Bash 3.0+ и Zsh 5.5.1 каждый поддерживает оба typeset -pи declare -pотличается только тем, что один является альтернативой для другого. Но я не проверял различия между этими двумя ключевыми словами, и я не проверял другие оболочки.
Если вам нужен ваш POSIX-совместимый скрипт, то вы не можете использовать массивы. Без массивов [ -n "{$var+x}" ]работает.
Код сравнения для разных методов в Bash
Эта функция сбрасывает переменную var, evalпередает переданный код, запускает тесты, чтобы определить, varустановлен ли evalкод d, и, наконец, показывает результирующие коды состояния для различных тестов.
Я пропускаю test -v var, [ -v var ]и [[ -v var ]]потому что они дают результаты, идентичные стандарту POSIX [ -n "${var+x}" ], при этом требуется Bash 4.2+. Я также пропускаю, typeset -pпотому что это так же, как declare -pв оболочках, которые я тестировал (Bash 3.0 через 5.0 и Zsh 5.5.1).
is-var-set-after(){# Set var by passed expression.
unset var
eval"$1"# Run the tests, in increasing order of accuracy.[-n "$var"]# (index 0 of) var is nonempty
nonempty=$?[-n "${var+x}"]# (index 0 of) var is set, maybe empty
plus=$?["${#var[@]}"!=0]# var has at least one index set, maybe empty
count=$?
declare -p var &>/dev/null # var has been declared (any type)
declared=$?# Show test results.
printf '%30s: %2s %2s %2s %2s\n'"$1" $nonempty $plus $count $declared
}
Код теста
Обратите внимание, что результаты теста могут быть неожиданными из-за того, что Bash рассматривает индексы нечислового массива как «0», если переменная не была объявлена как ассоциативный массив. Кроме того, ассоциативные массивы действительны только в Bash 4.0+.
# Header.
printf '%30s: %2s %2s %2s %2s\n'"test"'-n''+x''#@''-p'# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an# indexed array is also the nonindexed value, and non-numerical# indices in an array not declared as associative are the same as# index 0.
is-var-set-after "var=foo"# 0 0 0 0
is-var-set-after "var=(foo)"# 0 0 0 0
is-var-set-after "var=([0]=foo)"# 0 0 0 0
is-var-set-after "var=([x]=foo)"# 0 0 0 0
is-var-set-after "var=([y]=bar [x]=foo)"# 0 0 0 0# '[ -n "$var" ]' fails when var is empty.
is-var-set-after "var=''"# 1 0 0 0
is-var-set-after "var=([0]='')"# 1 0 0 0# Indices other than 0 are not detected by '[ -n "$var" ]' or by# '[ -n "${var+x}" ]'.
is-var-set-after "var=([1]='')"# 1 1 0 0
is-var-set-after "var=([1]=foo)"# 1 1 0 0
is-var-set-after "declare -A var; var=([x]=foo)"# 1 1 0 0# Empty arrays are only detected by 'declare -p'.
is-var-set-after "var=()"# 1 1 1 0
is-var-set-after "declare -a var"# 1 1 1 0
is-var-set-after "declare -A var"# 1 1 1 0# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after "unset var"# 1 1 1 1
Тестовый вывод
Испытуемые Мнемоники в заголовке строки соответствуют [ -n "$var" ], [ -n "${var+x}" ], [ "${#var[@]}" != 0 ], и declare -p var, соответственно.
declare -p var &>/dev/null (100%?) надежен для тестирования именованных переменных в Bash, начиная с версии 3.0.
[ -n "${var+x}" ] надежен в POSIX-совместимых ситуациях, но не может обрабатывать массивы.
Существуют другие тесты для проверки, является ли переменная непустой, и для проверки объявленных переменных в других оболочках. Но эти тесты не подходят ни для скриптов Bash, ни для POSIX.
Из ответов, которые я пробовал, этот ( declare -p var &>/dev/null) является ЕДИНСТВЕННЫМ, который работает. БЛАГОДАРЮ ВАС!
user1387866
2
@ mark-haferkamp Я попытался отредактировать ваш ответ, чтобы добавить критический предшествующий символ "/" к коду вашей функции, чтобы он читался, ... &> /dev/nullно SO не позволил бы мне редактировать один символ must (должно быть> 6 символов - даже пытался добавить пробел) но это не сработало). Кроме того, возможно, стоит изменить функцию для переключения $1для образца с именем переменной (например OUTPUT_DIR), поскольку, как вы указали, специальные переменные, такие как здесь $1, не работают. В любом случае, это критическое редактирование, иначе код пытается создать файл с именем nullв относительном каталоге dev. Кстати - отличный ответ!
Джоанна
Кроме того, использование имени переменной без префикса $ также работает: declare -p PATH &> /dev/nullвозвращает 0, где, как declare -p ASDFASDGFASKDF &> /dev/nullвозвращает 1. (на выпуске bash 5.0.11 (1))
joehanna
1
Отличная работа! 1 слово предостережения: declare varобъявляет переменную var, но не устанавливает ее в терминах set -o nounset: Test withdeclare foo bar=; set -o nounset; echo $bar; echo $foo
xebeche
@joehanna Спасибо, что поймали это без вести /! Я исправил это, но я думаю, что логика достаточно запутанная, чтобы оправдать функцию, особенно в свете комментария @ xebeche. @xebeche Это неудобно для моего ответа ... Похоже, мне придется попробовать что-то вроде declare -p "$1" | grep =или test -v "$1".
Марк Хаферкамп
19
Для тех, кто ищет для проверки неустановленный или пустой, когда в скрипте с set -u:
if[-z "${var-}"];then
echo "Must provide var environment variable. Exiting...."
exit 1fi
Регулярная [ -z "$var" ]проверка завершится неудачно с var; unbound variableif, set -uно [ -z "${var-}" ]развернется до пустой строки, если varне установлена, без сбоев.
Вам не хватает двоеточия. Должно быть ${var:-}, нет ${var-}. Но в Bash я могу подтвердить, что это работает даже без двоеточия.
Палек
3
${var:-}и ${var-}имею ввиду разные вещи. ${var:-}развернется в пустую строку, если не varустановлена или равна нулю, и ${var-}развернется в пустую строку, только если не установлена.
RubenLaguna
Просто узнал что-то новое, спасибо! Пропуск двоеточия приводит к проверке только для неустановленного параметра. Другими словами, если двоеточие включено, оператор проверяет наличие как параметра, так и того, что его значение не равно нулю; если двоеточие опущено, оператор проверяет только наличие. Здесь нет разницы, но приятно знать.
Палек
17
Вы хотите выйти, если он не установлен
Это сработало для меня. Я хотел, чтобы мой скрипт завершал работу с сообщением об ошибке, если параметр не был установлен.
#!/usr/bin/env bashset-o errexit
# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"
Возвращается с ошибкой при запуске
peek@peek:~$ ./setver.sh
./setver.sh: line 13:1:You must pass a version of the format 0.0.0 as the only argument
Только проверка, нет выхода - пусто и неустановлено недействительно
Попробуйте эту опцию, если вы просто хотите проверить, установлено ли значение set = VALID или unset / empty = INVALID.
Чтобы проверить, установлена ли переменная с непустым значением, используйте [ -n "$x" ] , как уже указали другие.
В большинстве случаев рекомендуется рассматривать переменную с пустым значением так же, как переменную, которая не установлена. Но вы можете различить два, если вам нужно: [ -n "${x+set}" ]( "${x+set}"расширяется до, setесли xустановлено и на пустую строку, если xне установлено).
Чтобы проверить, был ли передан параметр, проверьте $#, какое количество параметров было передано функции (или сценарию, когда функция отсутствует) (см . Ответ Пола ).
Прочитайте раздел «Расширение параметров» bash страницы. Расширение параметра не обеспечивает общий тест для устанавливаемой переменной, но есть несколько вещей, которые вы можете сделать с параметром, если он не установлен.
Например:
function a {
first_arg=${1-foo}# rest of the function}
будет установлен first_argравным, $1если он назначен, в противном случае он использует значение "foo". Если aабсолютно необходимо принять один параметр и не существует подходящего значения по умолчанию, вы можете выйти с сообщением об ошибке, если параметр не указан:
function a {: ${1?a must take a single argument}# rest of the function}
(Обратите внимание на использование :в качестве пустой команды, которая просто расширяет значения своих аргументов. Мы не хотим ничего делать $1в этом примере, просто завершите работу, если она не установлена)
Использование [[ -z "$var" ]]- это самый простой способ узнать, установлена ли переменная или нет, но эта опция -zне различает неустановленную переменную и переменную, для которой задана пустая строка:
declare -p: дает определение переменной, переданной в качестве параметра. Если он существует, возвращает 0, если нет, возвращает 1 и печатает сообщение об ошибке.
&> /dev/null: подавляет вывод, declare -pне влияя на его код возврата.
Ответы выше не работают, когда set -uвключена опция Bash . Кроме того, они не являются динамическими, например, как проверить, определена ли переменная с именем «dummy»? Попробуй это:
is_var_defined(){if[ $# -ne 1 ]then
echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
exit 1fi# Tricky. Since Bash option 'set -u' may be enabled, we cannot directly test if a variable# is defined with this construct: [ ! -z "$var" ]. Instead, we must use default value# substitution with this construct: [ ! -z "${var:-}" ]. Normally, a default value follows the# operator ':-', but here we leave it blank for empty (null) string. Finally, we need to# substitute the text from $1 as 'var'. This is not allowed directly in Bash with this# construct: [ ! -z "${$1:-}" ]. We need to use indirection with eval operator.# Example: $1="var"# Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"# Code execute: [ ! -z ${var:-} ]eval"[ ! -z \${$1:-} ]"return $?# Pedantic.}
вам нужно в кавычки $1, то есть [ ! -z "$1" ]. Или вы можете написать [[ ! -z $1 ]]в bash / ksh / zsh.
Жиль "ТАК ... перестать быть злым"
5
Это не удастся, если $1задана пустая строка.
Здравствуйте, до свидания
4
Мой предпочтительный способ заключается в следующем:
$ var=10
$ if! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$ unset -v var
$ if! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set
Таким образом, в принципе, если переменная установлена, она становится «отрицанием результата false» (что будетtrue = «установлено»).
И, если он не установлен, он станет «отрицанием полученного результата true» (так как пустой результат оценивается как true) (поэтому закончится как бы false= «НЕ установлено»).
if[[ ${1:+isset}]]then echo "It was set and not null.">&2else echo "It was not set or it was null.">&2fiif[[ ${1+isset}]]then echo "It was set but might be null.">&2else echo "It was was not set.">&2fi
Добро пожаловать в StackOverflow. Хотя ваш ответ приветствуется, лучше всего дать больше, чем просто код. Не могли бы вы добавить аргументацию к вашему ответу или небольшое объяснение? Смотрите эту страницу для других идей по расширению вашего ответа.
Celeo
0
Это то, что я использую каждый день:
## Check if a variable is set# param1 name of the variable#function is_set(){[[-n "${1}"]]&& test -n "$(eval "echo "\${${1}+x}"")"}
Это хорошо работает под Linux и Solaris вплоть до bash 3.0.
Начиная с Bash 2.0+ доступно косвенное расширение. Вы можете заменить long и complex (включая eval) test -n "$(eval "echo "\${${1}+x}"")"на эквивалент:[[ ${!1+x} ]]
0
Мне нравятся вспомогательные функции, чтобы скрыть грубые детали bash. В этом случае это добавляет еще больше (скрытой) грубости:
# The first ! negates the result (can't use -n to achieve this)# the second ! expands the content of varname (can't do ${$varname})functionIsDeclared_Tricky{local varname="$1"![-z ${!varname+x}]}
Поскольку у меня сначала были ошибки в этой реализации (вдохновленные ответами Дженса и Лайонела), я придумал другое решение:
# Ask for the properties of the variable - fails if not declaredfunctionIsDeclared(){
declare -p $1 &>/dev/null
}
Я нахожу это более прямым, более застенчивым и более легким для понимания / запоминания. Тестовый пример показывает, что это эквивалентно:
function main(){
declare -i xyz
local foo
local bar=local baz=''IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?"IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?"IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?"IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?"IsDeclared xyz; echo "IsDeclared xyz: $?"IsDeclared foo; echo "IsDeclared foo: $?"IsDeclared bar; echo "IsDeclared bar: $?"IsDeclared baz; echo "IsDeclared baz: $?"}
main
Тестовый пример показывает также , что local varделает НЕ объявлять вар (если не следует «=»). В течение достаточно долгого времени я думал, что я объявил переменные таким образом, просто чтобы обнаружить теперь, что я просто выразил свое намерение ... Я полагаю, что это неоперация.
Я в основном использовать этот тест , чтобы дать (и обратно) параметры функцию в некоторой степени «элегантный» и безопасном способе (почти напоминающий интерфейс ...):
#auxiliary functionsfunction die(){
echo "Error: $1"; exit 1}function assertVariableDeclared(){IsDeclared"$1"|| die "variable not declared: $1"}function expectVariables(){while(( $# > 0 )); do
assertVariableDeclared $1; shift
done}# actual examplefunction exampleFunction(){
expectVariables inputStr outputStr
outputStr="$inputStr world!"}function bonus(){local inputStr='Hello'local outputStr=# remove this to trigger error
exampleFunction
echo $outputStr
}
bonus
не будет работать, когда вы set -uдействуете, что напечатает unboud variableошибку
Майкл Хойбергер
0
Резюме
Используйте test -n "${var-}"для проверки, если переменная не пуста (и, следовательно, должна быть определена / установлена тоже)
Используйте, test ! -z "${var+}"чтобы проверить, определена ли переменная / установлена (даже если она пустая)
Обратите внимание, что первый вариант использования гораздо чаще встречается в сценариях оболочки, и это то, что вы обычно хотите использовать.
Ноты
Это решение должно работать во всех оболочках POSIX (sh, bash, zsh, ksh, dash)
Некоторые другие ответы на этот вопрос верны, но могут вводить в заблуждение людей, неопытных в создании сценариев оболочки, поэтому я хотел предоставить ответ TLDR, который будет наименее запутанным для таких людей.
объяснение
Чтобы понять , как это решение работает, вы должны понимать POSIX testкоманды и расширение параметров POSIX оболочки ( спецификация ), поэтому давайте рассмотрим самые основы , необходимых для понимания ответа.
Команда test оценивает выражение и возвращает истину или ложь (через состояние выхода). Оператор -nвозвращает true, если операнд является непустой строкой. Так, например, test -n "a"возвращает true, а test -n ""возвращает false. Теперь, чтобы проверить, не является ли переменная пустой (что означает, что она должна быть определена), вы можете использовать test -n "$var". Однако некоторые сценарии оболочки имеют опцию set ( set -u), которая заставляет любую ссылку на неопределенные переменные выдавать ошибку, поэтому, если переменная varне определена, выражение $aвызовет ошибку. Чтобы правильно обработать этот случай, вы должны использовать расширение переменной, которое скажет оболочке заменить переменную альтернативной строкой, если она не определена, избегая вышеупомянутой ошибки.
Расширение переменной ${var-}означает: если переменная varне определена (также называется «unset»), замените ее пустой строкой. Так test -n "${var-}"что вернет true, если $varне пусто, что почти всегда то, что вы хотите проверить в скриптах оболочки. Обратная проверка, если $varона не определена или не пуста, будет test -z "${var-}".
Теперь перейдем ко второму варианту использования: проверка, varопределена ли переменная , пустая или нет. Это менее распространенный вариант использования и немного более сложный, и я бы посоветовал вам прочитать отличный ответ Лайонела, чтобы лучше его понять.
Я думаю, что вы имеете в виду set -o nounset, нет set -o noun set. Это работает только для переменных, которые были exportотредактированы. Это также меняет ваши настройки таким образом, что это неудобно, чтобы отменить.
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi
,-v
тесте, хотя, по-видимому, он доступен только в новых версияхbash
и не переносится между оболочками.Ответы:
(Обычно) правильный путь
где
${var+x}
является расширением параметра , который оценивает ничего , еслиvar
не установлено, и заменяет строку вx
противном случае.Цитаты Отступление
Кавычки могут быть опущены (так что мы можем сказать
${var+x}
вместо"${var+x}"
), потому что этот синтаксис и использование гарантирует, что это будет расширяться только до чего-то, что не требует кавычек (так как оно расширяется доx
(которое не содержит разрывов слов, поэтому не нуждается в кавычках), или до ничего (что приводит к тому[ -z ]
, что удобно вычислять до того же значения (true), что[ -z "" ]
и так)).Однако, хотя кавычки могут быть безопасно опущены, и это было не сразу очевидно для всех (даже для первого автора этого объяснения кавычек, который также является основным кодировщиком Bash), иногда было бы лучше написать решение с кавычками как
[ -z "${var+x}" ]
, при очень маленькой возможной стоимости штрафа за скорость O (1). Первый автор также добавил это в качестве комментария рядом с кодом, использующим это решение, предоставив URL-адрес для этого ответа, который теперь также включает в себя объяснение того, почему цитаты можно безопасно опускать.(Часто) Неправильный путь
Это часто неправильно, поскольку не различает переменную, которая не установлена, и переменную, для которой задана пустая строка. То есть, если
var=''
, тогда вышеприведенное решение выведет "var is blank".Различие между unset и «set to empty string» является существенным в ситуациях, когда пользователь должен указать расширение или дополнительный список свойств, и если не указывать их, по умолчанию используется непустое значение, тогда как указание пустой строки должно заставить скрипт использовать пустое расширение или список дополнительных свойств.
Различие не может быть существенным в каждом сценарии все же. В тех случаях
[ -z "$var" ]
будет просто отлично.источник
${var+x}
это правильная замена для использования. Использование[ -z ${var:+x} ]
дает не отличный результат, чем[ -z "$var" ]
.[ -z "" -a -z ${var+x} ]
получаетbash: [: argument expected
в bash 4.3-ubuntu (но не, например, zsh). Мне действительно не нравится ответ с использованием синтаксиса, который в некоторых случаях срабатывает.[ -z $var ]
не более «неправильно», чем пропуск кавычек. В любом случае, вы делаете предположения о своем вкладе. Если вы хорошо относитесь к пустой строке как к неустановленной,[ -z $var ]
это все, что вам нужно.Для проверки ненулевой / ненулевой строковой переменной, т.е. если она установлена, используйте
Это противоположность
-z
. Я использую-n
больше, чем-z
.Вы бы использовали это как:
источник
[[ ]]
более[ ]
, а[[ ]]
более мощный и вызывает меньше проблем в определенных ситуациях (см этот вопрос для объяснения разницы между ними). Вопрос специально требует решения для bash и не содержит никаких требований по переносимости.[]
работает лучше, особенно для сценариев оболочки (не Bash).set -u
.-n
это тест по умолчанию, так что проще[ "$1" ]
или лучше[[ $1 ]]
работать. Также обратите внимание, что с[[ ]]
цитированием нет необходимости .Вот как проверить, является ли параметр не установленным , пустым («Null») или установленным со значением :
Источник: POSIX: Расширение параметров :
Чтобы показать это в действии:
источник
set foo; echo ${1:-set but null or unset}
echos "foo";set --; echo ${1:-set but null or unset}
отголоски установлены, но ноль ...set
:-): ${FOOBAR:=/etc/foobar.conf}
это установить значение по умолчанию для переменной, если она не установлена или равна нулю.parameter
любое имя переменной.word
является некоторой строкой, которую нужно заменить, в зависимости от того, какой синтаксис в таблице вы используете, и от того, установлена ли переменная$parameter
, установлена ли она на ноль или не установлена. Не для того, чтобы сделать вещи более сложными, ноword
также может включать переменные! Это может быть очень полезно для передачи необязательных аргументов, разделенных символом. Например:${parameter:+,${parameter}}
выводит запятую,,$parameter
если она установлена, но не равна нулю. В данном случаеword
это,${parameter}
Хотя большинство методов, изложенных здесь, верны, bash 4.2 поддерживает фактический тест на наличие переменной ( man bash ), а не тестирует значение переменной.
Примечательно, что этот подход не вызовет ошибки при использовании для проверки неустановленной переменной в
set -u
/set -o nounset
mode, в отличие от многих других подходов, таких как использование[ -z
.источник
[[ -v aaa ]]; echo $?
==>-bash: conditional binary operator expected
-bash: syntax error near 'aaa'
declare -a foo
Есть много способов сделать это, одним из которых является следующее:
Это успешно, если $ 1 ноль или не установлен
источник
[[ ]]
это не что иное, как ловушка переносимости.if [ -n "$1" ]
следует использовать здесь.foo=""
,$foo
имеет значение, но-z
просто сообщит, что он пуст. И-z $foo
взорвется, если у вас естьset -o nounset
.foo=
), тогда ответ Рассела верен.Я всегда нахожу таблицу POSIX в другом ответе медлительной, поэтому вот мое мнение:
Обратите внимание, что каждая группа (с и без предшествующего двоеточия) имеет одинаковый набор и неустановленные наблюдения , поэтому отличается только то, как обрабатываются пустые случаи.
С предыдущим двоеточием пустой и неустановленный регистры идентичны, поэтому я бы использовал те, где это возможно (т. Е. Используйте
:=
, а не только=
потому, что пустой регистр несовместим).Рубрики:
VARIABLE
не пусто (VARIABLE="something"
)VARIABLE
пусто / null (VARIABLE=""
)VARIABLE
не существует (unset VARIABLE
)Ценности:
$VARIABLE
означает, что результатом является исходное значение переменной."default"
означает, что результатом была предоставленная строка замены.""
означает, что результат равен нулю (пустая строка).exit 127
означает, что скрипт прекращает выполнение с кодом завершения 127.$(VARIABLE="default")
означает, что результатом является исходное значение переменной, и предоставленная строка замены назначается переменной для будущего использования.источник
VARIABLE=""
может быть написано какVARIABLE=
. Тем не менее, первый более читабелен.Чтобы увидеть, является ли переменная непустой, я использую
Противоположные тесты, если переменная не установлена или пуста:
Чтобы увидеть, установлена ли переменная (пустая или непустая), я использую
Противоположные тесты, если переменная не установлена:
источник
[ $isMac ] && param="--enable-shared"
${variable+x}
чтобы получить,x
если$variable
он установлен) почти полгода назад. Также в нем есть гораздо более подробное объяснение, почему это правильно.${variable+x}
менееВ современной версии Bash (4.2 или более поздней версии, я думаю, я точно не знаю) я бы попробовал это:
источник
[ -v "$VARNAME" ]
это не так, но просто выполняет другой тест. ПредположимVARNAME=foo
; Затем он проверяет, установлена ли переменная с именемfoo
.-v
не совместим с POSIX[: -v: unexpected operator
, он должен использоватьbash
вместоsh
.Хотя для аргументов обычно лучше всего проверить $ #, что, по моему мнению, является количеством аргументов.
источник
[ "$1" != "" ]
(или[ -n "$1" ]
) ...$1
задана пустая строка.$1
для нее задана пустая строка.set -o nounset
.Запись
Я даю сильно сфокусированный на Bash ответ из-за
bash
тега.Короткий ответ
Пока вы имеете дело только с именованными переменными в Bash, эта функция всегда должна сообщать вам, установлена ли переменная, даже если это пустой массив.
Почему это работает
В Bash (по крайней мере, начиная с версии 3.0), если
var
переменная объявлена / установлена,declare -p var
выводитdeclare
команду, которая установит переменнуюvar
в соответствии с ее текущим типом и значением, и возвращает код состояния0
(успех). Если значениеvar
не объявлено,declare -p var
выводится сообщение об ошибкеstderr
и возвращается код состояния1
. Используя&>/dev/null
, перенаправляет как обычный, такstdout
иstderr
выходной/dev/null
, никогда не будет видно и без изменения кода состояния. Таким образом, функция возвращает только код состояния.Почему другие методы (иногда) терпят неудачу в Bash
Когда этот метод не работает в Bash
Это работает только для именованных переменных ( в том числе
$_
), а не некоторых специальных переменных ($!
,$@
,$#
,$$
,$*
,$?
,$-
,$0
,$1
,$2
, ..., и любой я забыл). Поскольку ни один из них не является массивом, стиль POSIX[ -n "${var+x}" ]
работает для всех этих специальных переменных. Но остерегайтесь оборачивать его в функцию, так как многие специальные переменные изменяют значения / существование при вызове функций.Примечание о совместимости оболочки
Если в вашем скрипте есть массивы и вы пытаетесь сделать его совместимым с как можно большим количеством оболочек, рассмотрите возможность использования
typeset -p
вместоdeclare -p
. Я читал, что ksh поддерживает только первое, но не смог проверить это. Я знаю, что Bash 3.0+ и Zsh 5.5.1 каждый поддерживает обаtypeset -p
иdeclare -p
отличается только тем, что один является альтернативой для другого. Но я не проверял различия между этими двумя ключевыми словами, и я не проверял другие оболочки.Если вам нужен ваш POSIX-совместимый скрипт, то вы не можете использовать массивы. Без массивов
[ -n "{$var+x}" ]
работает.Код сравнения для разных методов в Bash
Эта функция сбрасывает переменную
var
,eval
передает переданный код, запускает тесты, чтобы определить,var
установлен лиeval
код d, и, наконец, показывает результирующие коды состояния для различных тестов.Я пропускаю
test -v var
,[ -v var ]
и[[ -v var ]]
потому что они дают результаты, идентичные стандарту POSIX[ -n "${var+x}" ]
, при этом требуется Bash 4.2+. Я также пропускаю,typeset -p
потому что это так же, какdeclare -p
в оболочках, которые я тестировал (Bash 3.0 через 5.0 и Zsh 5.5.1).Код теста
Обратите внимание, что результаты теста могут быть неожиданными из-за того, что Bash рассматривает индексы нечислового массива как «0», если переменная не была объявлена как ассоциативный массив. Кроме того, ассоциативные массивы действительны только в Bash 4.0+.
Тестовый вывод
Испытуемые Мнемоники в заголовке строки соответствуют
[ -n "$var" ]
,[ -n "${var+x}" ]
,[ "${#var[@]}" != 0 ]
, иdeclare -p var
, соответственно.Резюме
источник
declare -p var &>/dev/null
) является ЕДИНСТВЕННЫМ, который работает. БЛАГОДАРЮ ВАС!... &> /dev/null
но SO не позволил бы мне редактировать один символ must (должно быть> 6 символов - даже пытался добавить пробел) но это не сработало). Кроме того, возможно, стоит изменить функцию для переключения$1
для образца с именем переменной (напримерOUTPUT_DIR
), поскольку, как вы указали, специальные переменные, такие как здесь$1
, не работают. В любом случае, это критическое редактирование, иначе код пытается создать файл с именемnull
в относительном каталогеdev
. Кстати - отличный ответ!declare -p PATH &> /dev/null
возвращает 0, где, какdeclare -p ASDFASDGFASKDF &> /dev/null
возвращает 1. (на выпуске bash 5.0.11 (1))declare var
объявляет переменную var, но не устанавливает ее в терминахset -o nounset
: Test withdeclare foo bar=; set -o nounset; echo $bar; echo $foo
/
! Я исправил это, но я думаю, что логика достаточно запутанная, чтобы оправдать функцию, особенно в свете комментария @ xebeche. @xebeche Это неудобно для моего ответа ... Похоже, мне придется попробовать что-то вродеdeclare -p "$1" | grep =
илиtest -v "$1"
.Для тех, кто ищет для проверки неустановленный или пустой, когда в скрипте с
set -u
:Регулярная
[ -z "$var" ]
проверка завершится неудачно сvar; unbound variable
if,set -u
но[ -z "${var-}" ]
развернется до пустой строки, еслиvar
не установлена, без сбоев.источник
${var:-}
, нет${var-}
. Но в Bash я могу подтвердить, что это работает даже без двоеточия.${var:-}
и${var-}
имею ввиду разные вещи.${var:-}
развернется в пустую строку, если неvar
установлена или равна нулю, и${var-}
развернется в пустую строку, только если не установлена.Вы хотите выйти, если он не установлен
Это сработало для меня. Я хотел, чтобы мой скрипт завершал работу с сообщением об ошибке, если параметр не был установлен.
Возвращается с ошибкой при запуске
Только проверка, нет выхода - пусто и неустановлено недействительно
Попробуйте эту опцию, если вы просто хотите проверить, установлено ли значение set = VALID или unset / empty = INVALID.
Или даже короткие тесты ;-)
Только проверка, нет выхода - только пусто - НЕДОПУСТИМО
И это ответ на вопрос. Используйте это, если вы просто хотите проверить, установлено ли значение set / empty = VALID или unset = INVALID.
ПРИМЕЧАНИЕ: «1» в «..- 1}» не имеет значения, это может быть что угодно (например, x)
Короткие тесты
Я посвящаю этот ответ @ mklement0 (комментарии), который попросил меня ответить на вопрос точно.
Ссылка http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
источник
Чтобы проверить, установлена ли переменная с непустым значением, используйте
[ -n "$x" ]
, как уже указали другие.В большинстве случаев рекомендуется рассматривать переменную с пустым значением так же, как переменную, которая не установлена. Но вы можете различить два, если вам нужно:
[ -n "${x+set}" ]
("${x+set}"
расширяется до,set
еслиx
установлено и на пустую строку, еслиx
не установлено).Чтобы проверить, был ли передан параметр, проверьте
$#
, какое количество параметров было передано функции (или сценарию, когда функция отсутствует) (см . Ответ Пола ).источник
Прочитайте раздел «Расширение параметров»
bash
страницы. Расширение параметра не обеспечивает общий тест для устанавливаемой переменной, но есть несколько вещей, которые вы можете сделать с параметром, если он не установлен.Например:
будет установлен
first_arg
равным,$1
если он назначен, в противном случае он использует значение "foo". Еслиa
абсолютно необходимо принять один параметр и не существует подходящего значения по умолчанию, вы можете выйти с сообщением об ошибке, если параметр не указан:(Обратите внимание на использование
:
в качестве пустой команды, которая просто расширяет значения своих аргументов. Мы не хотим ничего делать$1
в этом примере, просто завершите работу, если она не установлена)источник
: ${var?message}
.В Bash вы можете использовать
-v
внутри[[ ]]
встроенного:источник
Использование
[[ -z "$var" ]]
- это самый простой способ узнать, установлена ли переменная или нет, но эта опция-z
не различает неустановленную переменную и переменную, для которой задана пустая строка:Лучше проверить это в соответствии с типом переменной: переменная env, параметр или обычная переменная.
Для переменной env:
Для параметра (например, чтобы проверить наличие параметра
$5
):Для обычной переменной (используя вспомогательную функцию, чтобы сделать это элегантным способом):
Ноты:
источник
Ответы выше не работают, когда
set -u
включена опция Bash . Кроме того, они не являются динамическими, например, как проверить, определена ли переменная с именем «dummy»? Попробуй это:Связанный: В Bash, как проверить, определена ли переменная в режиме "-u"
источник
eval "[ ! -z \${$1:-} ]"
в косвенную оценку:[ ! -z ${!1:-} ];
.Ты можешь сделать:
источник
-n
и не отрицать-z
.$1
, то есть[ ! -z "$1" ]
. Или вы можете написать[[ ! -z $1 ]]
в bash / ksh / zsh.$1
задана пустая строка.Мой предпочтительный способ заключается в следующем:
Таким образом, в принципе, если переменная установлена, она становится «отрицанием результата
false
» (что будетtrue
= «установлено»).И, если он не установлен, он станет «отрицанием полученного результата
true
» (так как пустой результат оценивается какtrue
) (поэтому закончится как быfalse
= «НЕ установлено»).источник
Или
Или
Или
источник
В оболочке вы можете использовать
-z
оператор True, если длина строки равна нулю.Простой однострочник для установки значения по умолчанию,
MY_VAR
если он не установлен, в противном случае вы можете вывести сообщение:источник
источник
$1
,$2
и до$N
всегда установлено. Извините, это не удалось.Я нашел (намного) лучший код для этого, если вы хотите что-то проверить
$@
.Почему это все? В
$@
Bash все существует, но по умолчанию оно пустое, поэтомуtest -z
иtest -n
не может вам помочь.Обновление: Вы также можете посчитать количество символов в параметрах.
источник
источник
Это то, что я использую каждый день:
Это хорошо работает под Linux и Solaris вплоть до bash 3.0.
источник
test -n "$(eval "echo "\${${1}+x}"")"
на эквивалент:[[ ${!1+x} ]]
Мне нравятся вспомогательные функции, чтобы скрыть грубые детали bash. В этом случае это добавляет еще больше (скрытой) грубости:
Поскольку у меня сначала были ошибки в этой реализации (вдохновленные ответами Дженса и Лайонела), я придумал другое решение:
Я нахожу это более прямым, более застенчивым и более легким для понимания / запоминания. Тестовый пример показывает, что это эквивалентно:
Тестовый пример показывает также , что
local var
делает НЕ объявлять вар (если не следует «=»). В течение достаточно долгого времени я думал, что я объявил переменные таким образом, просто чтобы обнаружить теперь, что я просто выразил свое намерение ... Я полагаю, что это неоперация.БОНУС: usecase
Я в основном использовать этот тест , чтобы дать (и обратно) параметры функцию в некоторой степени «элегантный» и безопасном способе (почти напоминающий интерфейс ...):
Если вызывается со всеми, объявлены переменные:
еще:
источник
После просмотра всех ответов это также работает:
если вы не поставите
SOME_VAR
вместо того, что у меня есть$SOME_VAR
, он установит пустое значение;$
Это необходимо для работы.источник
set -u
действуете, что напечатаетunboud variable
ошибкуРезюме
test -n "${var-}"
для проверки, если переменная не пуста (и, следовательно, должна быть определена / установлена тоже)test ! -z "${var+}"
чтобы проверить, определена ли переменная / установлена (даже если она пустая)Обратите внимание, что первый вариант использования гораздо чаще встречается в сценариях оболочки, и это то, что вы обычно хотите использовать.
Ноты
объяснение
Чтобы понять , как это решение работает, вы должны понимать POSIX
test
команды и расширение параметров POSIX оболочки ( спецификация ), поэтому давайте рассмотрим самые основы , необходимых для понимания ответа.Команда test оценивает выражение и возвращает истину или ложь (через состояние выхода). Оператор
-n
возвращает true, если операнд является непустой строкой. Так, например,test -n "a"
возвращает true, аtest -n ""
возвращает false. Теперь, чтобы проверить, не является ли переменная пустой (что означает, что она должна быть определена), вы можете использоватьtest -n "$var"
. Однако некоторые сценарии оболочки имеют опцию set (set -u
), которая заставляет любую ссылку на неопределенные переменные выдавать ошибку, поэтому, если переменнаяvar
не определена, выражение$a
вызовет ошибку. Чтобы правильно обработать этот случай, вы должны использовать расширение переменной, которое скажет оболочке заменить переменную альтернативной строкой, если она не определена, избегая вышеупомянутой ошибки.Расширение переменной
${var-}
означает: если переменнаяvar
не определена (также называется «unset»), замените ее пустой строкой. Такtest -n "${var-}"
что вернет true, если$var
не пусто, что почти всегда то, что вы хотите проверить в скриптах оболочки. Обратная проверка, если$var
она не определена или не пуста, будетtest -z "${var-}"
.Теперь перейдем ко второму варианту использования: проверка,
var
определена ли переменная , пустая или нет. Это менее распространенный вариант использования и немного более сложный, и я бы посоветовал вам прочитать отличный ответ Лайонела, чтобы лучше его понять.источник
Чтобы проверить, установлена ли переменная или нет
источник
$var
задана пустая строка.Если вы хотите проверить, является ли переменная связанной или несвязанной, это работает хорошо, даже после того, как вы включили опцию nounset:
источник
set -o nounset
, нетset -o noun set
. Это работает только для переменных, которые былиexport
отредактированы. Это также меняет ваши настройки таким образом, что это неудобно, чтобы отменить.