Как проверить, установлена ли переменная в Bash?

1189

Как узнать, установлена ​​ли переменная в Bash?

Например, как проверить, дал ли пользователь первый параметр функции?

function a {
    # if $1 is set ?
}
  • 12
    if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi .
  • 170
    Примечание для тех, кто ищет решения: на этот вопрос существует множество высоко оцененных ответов, которые отвечают на вопрос «переменная непустая». Более корректирующие решения («переменный набор») упоминаются в ответах Дженса и Лайонела ниже.
Показать ещё 10 комментариев
Теги:
variables

31 ответ

1799
Лучший ответ

(Обычно) Правильный путь

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 the empty string" имеет важное значение в ситуациях, когда пользователю необходимо указать расширение или дополнительный список свойств и не указывать им по умолчанию непустое значение, тогда как указание пустой строки должно сделайте скрипт пустым добавлением или списком дополнительных свойств.

Однако различие может быть не обязательно в каждом сценарии. В таких случаях [ -z "$var" ] будет в порядке.

  • 22
    @Garrett, ваше изменение сделало этот ответ неверным, ${var+x} - правильная замена для использования. Использование [ -z ${var:+x} ] дает не отличный результат, чем [ -z "$var" ] .
  • 9
    Это не работает Я получаю «not set» независимо от того, установлено ли значение var или нет (очищается с помощью «unset var», «echo $ var» не выводит).
Показать ещё 28 комментариев
744

Чтобы проверить строковую переменную не -n ULL/не -z, т.е. Если она установлена, используйте

if [ -n "$1" ]

Это противоположность -z. Я использую -n больше, чем -z.

Вы бы использовали это как:

if [ -n "$1" ]; then
  echo "You supplied the first parameter!"
else
  echo "First parameter not supplied."
fi
  • 75
    Я обычно предпочитаю [[ ]] чем [ ] , так как [[ ]] более мощный и вызывает меньше проблем в определенных ситуациях (см. Этот вопрос для объяснения различия между ними). Вопрос специально требует решения bash и не содержит никаких требований по переносимости.
  • 16
    Вопрос заключается в том, как можно увидеть , если переменная установлена. Тогда вы не можете предположить , что переменная установлена.
Показать ещё 6 комментариев
408

Здесь, как проверить, установлен ли параметр unset, или пустой ( "Null" ) или со значением:

+--------------------+----------------------+-----------------+-----------------+
|                    |       parameter      |     parameter   |    parameter    |
|                    |   Set and Not Null   |   Set But Null  |      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 |
+--------------------+----------------------+-----------------+-----------------+

Источник: POSIX: расширение параметров:

Во всех случаях, показанных с помощью "substitute", выражение заменяется показанным значением. Во всех случаях, показанных с помощью "assign", этому назначению присваивается значение, которое также заменяет выражение.

  • 0
    Это не работает, если параметр равен 1 , т.е. если вы хотите проверить, установлен ли первый аргумент скрипта или нет.
  • 5
    @HelloGoodbye Да, это работает: set foo; echo ${1:-set but null or unset} echo "foo"; set --; echo ${1:-set but null or unset} эхо установлено, но null ...
Показать ещё 11 комментариев
165

Хотя большинство методов, изложенных здесь, верны, bash 4.2 поддерживает фактический тест на наличие переменной (man bash), а не тестирует значение переменной.

[[ -v foo ]]; echo $?
# 1

foo=bar
[[ -v foo ]]; echo $?
# 0

foo=""
[[ -v foo ]]; echo $?
# 0

Примечательно, что этот подход не вызовет ошибки при использовании для проверки set -u переменной в режиме set -u/set -o nounset, в отличие от многих других подходов, таких как использование [ -z.

  • 7
    В bash 4.1.2, независимо от того, установлена ли переменная, [[ -v aaa ]]; echo $? ==> -bash: conditional binary operator expected -bash: syntax error near 'aaa'
  • 27
    Аргумент '-v' для встроенной команды 'test' был добавлен в bash 4.2.
Показать ещё 6 комментариев
161

Существует много способов сделать это, одним из которых является следующее:

if [ -z "$1" ]

Это выполняется, если $1 является null или unset

  • 0
    Я думаю, что это должно быть быстрее, чем обычный [x "$ var" = x]. Просто хотел указать на это. Существует множество решений, но для сумасшедших людей, использующих bash вместо perl, это важно.
  • 38
    Существует разница между неустановленным параметром и параметром с нулевым значением.
Показать ещё 10 комментариев
59

Чтобы узнать, не переменна ли переменная, я использую

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 all
if [[ ! ${1+x} ]]; then ...   # We were called with no arguments
  • 0
    Я тоже использовал это некоторое время; только в сокращенном виде: [ $isMac ] && param="--enable-shared"
  • 0
    @Bhaskar Я думаю, это потому, что этот ответ уже предоставил практически тот же ответ (используйте ${variable+x} чтобы получить x если установлена $variable ) почти полгода назад. Также в нем есть гораздо более подробное объяснение, почему это правильно.
48

Я всегда нахожу таблицу POSIX в другом ответе медленным, чтобы понять, поэтому здесь я беру на себя:

   +----------------------+------------+-----------------------+-----------------------+
   |   if VARIABLE is:    |    set     |         empty         |        unset          |
   +----------------------+------------+-----------------------+-----------------------+
 - |  ${VARIABLE-default} | $VARIABLE  |          ""           |       "default"       |
 = |  ${VARIABLE=default} | $VARIABLE  |          ""           | $(VARIABLE="default") |
 ? |  ${VARIABLE?default} | $VARIABLE  |          ""           |       exit 127        |
 + |  ${VARIABLE+default} | "default"  |       "default"       |          ""           |
   +----------------------+------------+-----------------------+-----------------------+
:- | ${VARIABLE:-default} | $VARIABLE  |       "default"       |       "default"       |
:= | ${VARIABLE:=default} | $VARIABLE  | $(VARIABLE="default") | $(VARIABLE="default") |
:? | ${VARIABLE:?default} | $VARIABLE  |       exit 127        |       exit 127        |
:+ | ${VARIABLE:+default} | "default"  |          ""           |          ""           |
   +----------------------+------------+-----------------------+-----------------------+

Обратите внимание, что каждая группа (с и без предшествующего двоеточия) имеет одинаковый набор и отменяет случаи, поэтому единственное, что отличается, - это то, как обрабатываются пустые случаи.

В предыдущем двоеточии пустые и неустановленные случаи идентичны, поэтому я бы использовал их там, где это было возможно (т.е. использовать :=, а не только =, потому что пустой случай несовместим).

Заголовки:

  • set VARIABLE не является пустым (VARIABLE="something")
  • пустое средство VARIABLE пусто /null (VARIABLE="")
  • unset означает VARIABLE не существует (unset VARIABLE)

Значения:

  • $VARIABLE означает, что результатом является исходное значение переменной.
  • "default" означает, что результатом была строка замены.
  • "" означает, что результат равен null (пустая строка).
  • exit 127 означает, что script прекращает выполнение с кодом выхода 127.
  • $(VARIABLE="default") означает, что результатом является исходное значение переменной, а предоставленная строка замены назначается переменной для будущего использования.
  • 1
    Вы исправили только те, которые являются реальными ошибками кодирования (случаи нежелательной косвенности при работе с переменными). Я сделал правку, чтобы исправить еще несколько случаев, когда доллар имеет значение при интерпретации описания. Кстати, все переменные оболочки (за исключением массивов) являются строковыми переменными; может случиться так, что они содержат строку, которую можно интерпретировать как число. Разговор о струнах только затуманивает сообщение. Кавычки не имеют ничего общего со строками, они просто альтернатива экранированию. VARIABLE="" может быть записано как VARIABLE= . Тем не менее, первый более читабелен.
  • 1
    Ах, это проясняет - цени совет!
31

В современной версии Bash (4.2 или более поздней, я думаю, я точно не знаю), я бы попробовал это:

if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigil
then
    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
  • 4
    Также обратите внимание, что [ -v "$VARNAME" ] не является неправильным, а просто выполняет другой тест. Предположим, VARNAME=foo ; Затем он проверяет, установлена ли переменная с именем foo .
  • 4
    Примечание для тех, кто хочет переносимости, -v не совместим с POSIX
Показать ещё 1 комментарий
18
if [ "$1" != "" ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

Хотя для аргументов, как правило, лучше всего проверять $#, что является числом аргументов, на мой взгляд.

if [ $# -gt 0 ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi
  • 1
    Первый тест задом наперед; Я думаю, что вы хотите [ "$1" != "" ] (Или [ -n "$1" ] ) ...
  • 0
    @ Гордон, исправлено!
Показать ещё 3 комментария
15

Вы хотите выйти, если он отключен

Это сработало для меня. Я хотел, чтобы мой script вышел с сообщением об ошибке, если параметр не был установлен.

#!/usr/bin/env bash

set -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

Только проверка, без выхода - Empty и Unset - INVALID

Попробуйте этот параметр, если вы просто хотите проверить, установлено ли value = VALID или unset/empty = INVALID.

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
if [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

Или, даже короткие тесты; -)

[ "${TSET:-}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"

Проверить только, нет выхода - только пустой - INVALID

И это ответ на вопрос. Используйте это, если вы просто хотите проверить, установлено ли значение/пусто = VALID или unset = INVALID.

ПРИМЕЧАНИЕ. "1" в "..-1" "незначительно, это может быть что угодно (например, x)

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TUNSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

Короткие тесты

[ "${TSET+1}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET+1}" ] && echo "VALID" || echo "INVALID"

Я посвящаю этот ответ @mklement0 (комментарии), который бросил вызов мне, чтобы ответить на вопрос точно.

Ссылка http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02

14

Прочтите раздел "Расширение параметров" на странице руководства 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
}

(Обратите внимание на использование : как команды null, которая просто расширяет значения его аргументов. Мы не хотим ничего делать с $1 в этом примере, просто выйдите, если он не установлен)

  • 1
    Я сбит с толку, что ни один из других ответов не упоминает о простом и элегантном : ${var?message} .
12

В bash вы можете использовать -v внутри встроенного [[ ]]:

#! /bin/bash -u

if [[ ! -v SOMEVAR ]]; then
    SOMEVAR='hello'
fi

echo $SOMEVAR
12

Чтобы проверить, установлена ​​ли переменная с непустым значением, используйте [ -n "$x" ], как уже указывали другие.

В большинстве случаев рекомендуется обрабатывать переменную с пустым значением так же, как и переменная, которая не установлена. Но вы можете различить два, если вам нужно: [ -n "${x+set}" ] ("${x+set}" расширяется до set, если x установлено и пустая строка, если x не установлена).

Чтобы проверить, был ли передан параметр, test $#, который представляет собой число параметров, переданных функции (или в script, если не в функции) (см. Ответ Павла).

11

Для тех, кто хочет проверить, не сброшен или нет, когда в скрипте с set -u:

if [ -z "${var-}" ]; then
   echo "Must provide var environment variable. Exiting...."
   exit 1
fi

Регулярная [ -z "$var" ] не будет выполнена с var; unbound variable var; unbound variable если set -u но [ -z "${var-}" ] расширяется до пустой строки, если var не устанавливается без сбоев.

  • 0
    Вам не хватает двоеточия. Это должно быть ${var:-} , а не ${var-} . Но в Bash я могу подтвердить, что это работает даже без двоеточия.
  • 2
    ${var:-} и ${var-} означают разные вещи. ${var:-} развернется в пустую строку, если var unset или null, а ${var-} в пустую строку, только если не установлен.
Показать ещё 1 комментарий
4

Ответы выше не работают, если включена опция Bash set -u. Кроме того, они не являются динамическими, например, как проверяется переменная с именем "dummy"? Попробуйте следующее:

is_var_defined()
{
    if [ $# -ne 1 ]
    then
        echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
        exit 1
    fi
    # 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.
}

Связано: В Bash, как я могу проверить, определена ли переменная в "-u" Режим

  • 1
    Мне бы очень хотелось узнать, почему этот ответ был отклонен ... Прекрасно работает для меня.
  • 0
    В Bash вы можете сделать то же самое без eval: замените eval "[ ! -z \${$1:-} ]" на косвенную оценку: [ ! -z ${!1:-} ]; ,
Показать ещё 2 комментария
4

Вы можете сделать:

function a {
        if [ ! -z "$1" ]; then
                echo '$1 is set'
        fi
}
  • 7
    Или вы можете сделать -n и не отрицать -z .
  • 1
    вам нужно кавычки около $1 , т. е. [ ! -z "$1" ] . Или вы можете написать [[ ! -z $1 ]] в bash / ksh / zsh.
Показать ещё 1 комментарий
2

Если var может быть массивом, то подстановка параметра [ -z "${var+x}" ] неверна. Чтобы быть уверенным в Bash, вам нужно использовать синтаксис массива, например, [ "${#var[@]}" = 0 ], как показано ниже.

is-var-set () {
    results="\${var+x}=${var+x}\t\${#var[@]}=${#var[@]}"
    if [ -z "${var+x}" ] && [ "${#var[@]}" = 0 ]; then
        echo -e "$1: var unset.\t$results"
    elif [ -n "${var+x}" ] && [ "${#var[@]}" != 0 ]; then
        echo -e "$1: var is set. \t$results"
    else
        echo -e "$1: Is var set? \t$results"
    fi
    unset var # so we don't have to do it everywhere else
}

Практически во всех случаях они согласны. Единственная ситуация, в которой я нашел метод массива, является более точной, когда переменная является непустым массивом с нулевой позицией 0 (например, в тестах 7 и A ниже). Это несоответствие происходит из-за того, что $var является сокращением для ${var[0]}, поэтому [ -z "${var+x}" ] не проверяет весь массив.

Вот мои тесты:

unset var;      is-var-set 1 # var unset
var='';         is-var-set 2 # var[0] set to ''
var=foo;        is-var-set 3 # var[0] set to 'foo'
var=();         is-var-set 4 # var unset (all indices)
var=(foo);      is-var-set 5 # var[0] set to 'foo'
var=([0]=foo);  is-var-set 6 # var[0] set to 'foo'
var=([1]=foo);  is-var-set 7 # var[0] unset, but var[1] set to 'foo'
declare -a var; is-var-set 8 # var empty, but declared as an array
declare -A var; is-var-set 9 # var empty, but declared as an associative array
declare -A var  # Because is-var-set() conveniently unsets it
var=([xz]=foo); is-var-set A # var[xz] set to 'foo', but var otherwise empty
declare -a var  # Demonstrate that Bash knows about var, even when there's
declare -A var; is-var-set B # apparently no way to just _check_ its existence

Вот вывод:

1: var unset. ${var+x}=       ${#var[@]}=0
2: var is set.  ${var+x}=x      ${#var[@]}=1
3: var is set.  ${var+x}=x      ${#var[@]}=1
4: var unset. ${var+x}=       ${#var[@]}=0
5: var is set.  ${var+x}=x      ${#var[@]}=1
6: var is set.  ${var+x}=x      ${#var[@]}=1
7: Is var set?  ${var+x}=       ${#var[@]}=1
8: var unset. ${var+x}=       ${#var[@]}=0
9: var unset. ${var+x}=       ${#var[@]}=0
A: Is var set?  ${var+x}=       ${#var[@]}=1
./foo.sh: line 26: declare: var: cannot convert indexed to associative array
B: var unset. ${var+x}=       ${#var[@]}=0

В сумме:

  • Синтаксис раскрытия параметров ${var+x} в большинстве случаев работает так же, как синтаксис массива ${#var[@]}, например, проверка параметров в функциях. Единственный способ, которым этот случай может выйти из строя, - это если будущая версия Bash добавит способ передачи массивов в функции без преобразования содержимого в отдельные аргументы.
  • Синтаксис массива необходим для непустых массивов (ассоциативных или нет) с нулевым элементом 0.
  • Ни один из синтаксисов не объясняет, что происходит, если было использовано declare -a var, не присваивающее даже нулевое значение где-либо в массиве. Bash все еще различает случай где-то (как видно в тесте B выше), поэтому этот ответ не является надежным. К счастью, Bash преобразует экспортированные переменные среды в строки при запуске программы/скрипта, поэтому любые проблемы с объявленными, но неустановленными переменными будут содержаться в одном скрипте, по крайней мере, если он не использует другие скрипты.
  • 0
    Из ответов, которые я пробовал, этот ( declare -p var &>/dev/null ) является ЕДИНСТВЕННЫМ, который работает. БЛАГОДАРЮ ВАС!
2

Использование [[ -z "$var" ]] - это самый простой способ узнать, была ли установлена переменная или нет, но эта опция -z не различает -z переменную и переменную, установленную в пустую строку:

$ set=''
$ [[ -z "$set" ]] && echo "Set" || echo "Unset" 
Unset
$ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
Unset

Лучше всего проверить его в соответствии с типом переменной: переменной env, параметром или обычной переменной.

Для переменной env:

[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"

Для параметра (например, для проверки существования параметра $5):

[[ $# -ge 5 ]] && echo "Set" || echo "Unset"

Для регулярной переменной (используя вспомогательную функцию, чтобы сделать это элегантным способом):

function declare_var {
   declare -p "$1" &> /dev/null
   return $?
}
declare_var "var_name" && echo "Set" || echo "Unset"

Заметки:

  • $# : указывает количество позиционных параметров.
  • declare -p : дает вам определение переменной, переданной как параметр. Если он существует, возвращает 0, если нет, возвращает 1 и выводит сообщение об ошибке.
  • $? : выдает код состояния последней выполненной команды.
1

Мой предпочтительный способ:

$var=10
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$unset var
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set

В принципе, если переменная установлена, она становится "отрицанием результирующего false" (что будет установлено true= ").

И, если он не установлен, он станет "отрицанием результирующего true" (поскольку пустой результат оценивается как true) (поэтому он заканчивается как false= "NOT set" ).

1

В оболочке вы можете использовать оператор -z, который является True, если длина строки равна нулю.

Простой однострочный набор для установки по умолчанию MY_VAR, если он не установлен, в противном случае вы можете отобразить сообщение:

[[ -z "$MY_VAR" ]] && MY_VAR="default"
[[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."
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})
function IsDeclared_Tricky
{
  local varname="$1"
  ! [ -z ${!varname+x} ]
}

Поскольку у меня сначала были ошибки в этой реализации (вдохновленные ответами Йенса и Лионеля), я придумал другое решение:

# Ask for the properties of the variable - fails if not declared
function IsDeclared()
{
  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 NOT объявляет var (если не следовать '='). В течение некоторого времени я думал, что я объявил переменные таким образом, просто чтобы узнать теперь, что я просто выразил свое намерение... Это не-op, я думаю.

IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
Панель IsDeclared_Tricky: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz: 1
IsDeclared foo: 1
Панель IsDeclared: 0
IsDeclared baz: 0

БОНУС: usecase

В основном я использую этот тест, чтобы дать (и возвращать) параметры функциям несколько "элегантным" и безопасным способом (почти напоминающим интерфейс...):

#auxiliary functions
function 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 example
function exampleFunction()
{
  expectVariables inputStr outputStr
  outputStr="$inputStr world!"
}

function bonus()
{
  local inputStr='Hello'
  local outputStr= # remove this to trigger error
  exampleFunction
  echo $outputStr
}

bonus

Если вызов со всеми требует объявленных переменных:

Привет мир!

еще:

Ошибка: переменная не объявлена: outputStr

0
if [[ ${!xx[@]} ]] ; then echo xx is defined; fi
  • 11
    Добро пожаловать в StackOverflow. Хотя ваш ответ приветствуется, лучше всего дать больше, чем просто код. Не могли бы вы добавить аргументацию к вашему ответу или небольшое объяснение? Смотрите эту страницу для других идей по расширению вашего ответа.
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-3.00$ myvar="TEST"
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ mavar=""
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ unset myvar
bash-3.00$ is_set myvar ; echo $?
1
  • 1
    Начиная с Bash 2.0+ доступно косвенное расширение. Вы можете заменить длинный и сложный (включая eval) test -n "$(eval "echo "\${${1}+x}"")" на эквивалентный: [[ ${!1+x} ]]
0
[[ $foo ]]

или

(( ${#foo} ))

или

let ${#foo}

или

declare -p foo
0

Я нашел (намного) лучший код, чтобы сделать это, если вы хотите проверить что-либо в $@.

if [[ $1 = "" ]]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi

Почему все это? Все в $@ существует в Bash, но по умолчанию оно пустое, поэтому test -z и test -n не могут вам помочь.

Обновление: Вы можете также подсчитать количество символов в параметрах.

if [ ${#1} = 0 ]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi
  • 0
    С set -o errexit это может работать не так хорошо ...
  • 0
    Я знаю, но это все. Если что-то пусто, вы получите ошибку! Сожалею. :П
0

Я всегда использую этот метод, основываясь на том, что его легко понять кто-либо, кто видит код в первый раз:

if [ "$variable" = "" ]
    then
    echo "Variable X is empty"
fi

И, если вы хотите проверить, не пусто ли,

if [ ! "$variable" = "" ]
    then
    echo "Variable X is not empty"
fi

Что это.

  • 4
    Вопрос в том, как проверить, установлена ли переменная, а не в том, является ли переменная пустой.
  • 0
    Вам, вероятно, нужно использовать [[ ... ]] вместо [ ... ] . Последняя на самом деле является внешней командой и не будет иметь никакого представления о том, установлена ли переменная или нет.
0
if [[ ${1:+isset} ]]
then echo "It was set and not null." >&2
else echo "It was not set or it was null." >&2
fi

if [[ ${1+isset} ]]
then echo "It was set but might be null." >&2
else echo "It was was not set." >&2
fi
  • 0
    $1 , $2 и до $N всегда установлены. Извините, это не удалось.
  • 0
    @ZDroid Попробуйте: gist.github.com/solidsnack/7559844
Показать ещё 1 комментарий
-1

Функции для проверки, объявлена ​​ли переменная /unset

включая пустой $array=()


Следующие функции проверяют, существует ли данное имя как переменная

# The first parameter needs to be the name of the variable to be checked.
# (See example below)

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}
  • При первом тестировании, если переменная (un) установлена, вызов declare можно избежать, если это не необходимо.
  • Если, однако, $1 содержит имя пустого $array=(), вызов объявления будет гарантировать, что мы получим правильный результат
  • До сих пор не передавалось много данных в /dev/null, поскольку declare вызывается только в том случае, если переменная не установлена ​​или пустой массив.

Эти функции будут проверяться, как показано в следующих условиях:

a;       # is not declared
a=;      # is declared
a="foo"; # is declared
a=();    # is declared
a=("");  # is declared
unset a; # is not declared

a;       # is unset
a=;      # is not unset
a="foo"; # is not unset
a=();    # is not unset
a=("");  # is not unset
unset a; # is unset

.

Подробнее...

и тест script см. мой ответ на вопрос "Как проверить, существует ли переменная в bash?" .

Примечание: Аналогичное использование declare -p, как это показано также Peregring-lk ответ, поистине случайный. В противном случае, я бы, конечно, придумал это!

-1

Чтобы проверить, установлен ли параметр var или нет

var=""; [[ $var ]] && echo "set" || echo "not set"
  • 3
    Это не удастся, если $var установлен в пустую строку.
-2

Если вы хотите проверить, что переменная связана или несвязана, это хорошо работает, даже после того, как вы включили опцию nounset:

set -o noun set

if printenv variableName >/dev/null; then
    # variable is bound to a value
else
    # variable is unbound
fi
  • 0
    Я думаю, что вы имеете в виду set -o nounset , а не set -o noun set . Это работает только для переменных, которые были export . Это также изменяет ваши настройки таким образом, что это неудобно, чтобы отменить.
-2
case "$1" in
 "") echo "blank";;
 *) echo "set"
esac
  • 3
    Это не удастся, если $1 установлен на пустую строку.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню