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

Фактически делегаты - это тип (класс). Это просто синтаксический сахар, если вы можете, когда вы объявляете тип делегата

public delegate int PerformCalculation(int x, int y);

Делегат - это тип, который надежно инкапсулирует метод. Типы делегатов выводятся из класса Delegate в .NET Framework.

blockquote>

http://msdn.microsoft.com/en-us/library/ms173172%28v=vs.80%29.aspx

Итак, когда вы объявляете делегата вне класса, вы фактически создаете новый тип / класс. Затем вы создаете экземпляр делегата в классе.

С учетом сказанного, как замечает замечание @Mehrdad, все должно быть внутри класса, не является обязательным для ООП.

1323
задан nbro 7 September 2016 в 16:27
поделиться

20 ответов

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

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}"), потому что этот синтаксис & amp; использование гарантирует, что это будет расширяться только до чего-то, что не требует кавычек (поскольку оно либо расширяется до 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" ] будет просто отлично.

1983
ответ дан Benjamin Toueg 7 September 2016 в 16:27
поделиться
case "$1" in
 "") echo "blank";;
 *) echo "set"
esac
-2
ответ дан ghostdog74 7 September 2016 в 16:27
поделиться
[[ $foo ]]

Или

(( ${#foo} ))

Или

let ${#foo}

Или

declare -p foo
0
ответ дан Steven Penny 7 September 2016 в 16:27
поделиться
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
ответ дан solidsnack 7 September 2016 в 16:27
поделиться

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

#! /bin/bash -u

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

echo $SOMEVAR
13
ответ дан AlejandroVD 7 September 2016 в 16:27
поделиться

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

set -o noun set

if printenv variableName >/dev/null; then
    # variable is bound to a value
else
    # variable is unbound
fi
-1
ответ дан user1857592 7 September 2016 в 16:27
поделиться

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

if [ -z "$1" ]

Это успешно, если $ 1 ноль или не установлен

174
ответ дан Steel Brain 7 September 2016 в 16:27
поделиться

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

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

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

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

Вот и все.

0
ответ дан Peter Mortensen 7 September 2016 в 16:27
поделиться

Ответы выше не работают, если включена опция 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 проверить, определена ли переменная в & quot; -u & quot; Режим

4
ответ дан Community 7 September 2016 в 16:27
поделиться

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

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

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

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

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

198
ответ дан Mark Amery 7 September 2016 в 16:27
поделиться

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

if [ -n "$1" ]

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

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

if [ -n "$1" ]; then
  echo "You supplied the first parameter!"
else
  echo "First parameter not supplied."
fi
781
ответ дан Joshua Pinter 7 September 2016 в 16:27
поделиться

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

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
62
ответ дан phkoester 7 September 2016 в 16:27
поделиться

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

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

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

14
ответ дан Community 7 September 2016 в 16:27
поделиться

Вы хотите выйти, если он не установлен

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

#!/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

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

Попробуйте эту опцию, если вы просто хотите проверить, если значение установлено = VALID или не установлено / пусто = 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"

Только проверка, нет выхода - только пусто НЕВЕРНО

И это ответ на вопрос. Используйте это, если вы просто хотите проверить, установлено ли значение set / empty = 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

16
ответ дан Jarrod Chesney 7 September 2016 в 16:27
поделиться

Использование [[ -z "$var" ]] - это самый простой способ узнать, была ли переменная установлена ​​или нет, но эта опция -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
}
declare_var "var_name" && echo "Set" || echo "Unset"

Примечания:

  • $#: дает вам количество позиционных параметров.
  • declare -p: дает определение переменной, переданной в качестве параметра. Если он существует, возвращает 0, если нет, возвращает 1 и печатает сообщение об ошибке.
  • &> /dev/null: подавляет вывод из declare -p, не влияя на его код возврата.
5
ответ дан Mark Haferkamp 7 September 2016 в 16:27
поделиться

Мне нравятся вспомогательные функции, чтобы скрыть грубые детали 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 НЕ НЕ объявляет var (если не следует '='). В течение достаточно долгого времени я думал, что я объявил переменные таким образом, просто чтобы теперь обнаружить, что я просто выразил свое намерение ... Я полагаю, это неоперация.

IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
IsDeclared_Tricky bar: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz 1
IsDeclared boo: 1
IsDeclared bar: 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

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

Hello world!

else:

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

0
ответ дан Daniel S 7 September 2016 в 16:27
поделиться

Я всегда нахожу таблицу 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"  |          ""           |          ""           |
   +----------------------+------------+-----------------------+-----------------------+

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

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

Заголовки:

  • set означает, что VARIABLE не пусто (VARIABLE="something")
  • пусто означает, что VARIABLE пуст / ноль (VARIABLE="")
  • unset означает, что VARIABLE не существует (unset VARIABLE)

Значения:

  • $VARIABLE означает, что результатом является исходное значение переменной.
  • "default" означает, что результатом была предоставленная замещающая строка.
  • "" означает, что результат равен нулю (пустая строка).
  • exit 127 означает, что скрипт прекращает выполнение с кодом завершения 127.
  • $(VARIABLE="default") означает, что результатом является исходное значение переменной , а предоставленная строка замены присваивается переменной для будущего использования.
58
ответ дан deizel 7 September 2016 в 16:27
поделиться

Заметка

Я даю сильно сфокусированный на Bash ответ из-за тега bash.

Короткий ответ

Пока вы имеете дело только с именованными переменными в Bash, эта функция всегда должна сообщать вам, установлена ​​ли переменная, даже если это пустой массив.

is-variable-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

Это работает только для именованных переменных (включая

Заметка

Я даю сильно сфокусированный на Bash ответ из-за тега [114].

Короткий ответ

Пока вы имеете дело только с именованными переменными в Bash, эта функция всегда должна сообщать вам, установлена ​​ли переменная, даже если это пустой массив.

[110]

Почему это работает

В Bash (по крайней мере, начиная с 3.0), если [115] является объявленной / установленной переменной, то [116] выводит команду [117], которая бы установите переменную [118] равной ее текущему типу и значению и возвращает код состояния [119] (успех). Если [1110] не объявлено, то [1111] выводит сообщение об ошибке в [1112] и возвращает код состояния [1113]. Используя [1114], перенаправляет как обычный вывод [1115], так и [1116] на [1117], чтобы его никогда не было видно, и без изменения кода состояния. Таким образом, функция возвращает только код состояния.

Почему другие методы (иногда) терпят неудачу в Bash

  • [1118]: Эта проверка только, если [1119] не пусто. (В Bash [1120] совпадает с [1121].)
  • [1122]: Это только проверяет, установлено ли [1123].
  • [1124]: Проверяется только, установлен ли хотя бы один индекс [1125].

Когда этот метод не работает в Bash

Это работает только для именованных переменных (включая [1126]), а не определенных специальных переменных ($!, $@, $# , $, $*, $?, $-, [1134], $1, $2, ... и все, что я мог забыть). Поскольку ни один из них не является массивом, стиль POSIX [ -n "${var+x}" ] работает для всех этих специальных переменных. Но остерегайтесь оборачивать его в функцию, так как многие специальные переменные меняют значения / существование при вызове функций.

Замечание по совместимости оболочки

Если в вашем скрипте есть массивы, и вы пытаетесь сделать его совместимым с максимально возможным количеством оболочек, рассмотрите возможность использования typeset -p вместо declare -p. Я читал, что ksh поддерживает только первое, но не смог проверить это. Я знаю, что Bash 3.0+ и Zsh 5.5.1 поддерживают оба typeset -p и declare -p, отличающиеся только тем, что одно является альтернативой другому. Но я не проверял различия между этими двумя ключевыми словами и не проверял другие оболочки.

Если вам нужен ваш сценарий для совместимости с POSIX sh, вы не можете использовать массивы. Без массивов [ -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, соответственно.

                         test: -n +x #@ -p
                      var=foo:  0  0  0  0
                    var=(foo):  0  0  0  0
                var=([0]=foo):  0  0  0  0
                var=([x]=foo):  0  0  0  0
        var=([y]=bar [x]=foo):  0  0  0  0
                       var='':  1  0  0  0
                 var=([0]=''):  1  0  0  0
                 var=([1]=''):  1  1  0  0
                var=([1]=foo):  1  1  0  0
declare -A var; var=([x]=foo):  1  1  0  0
                       var=():  1  1  1  0
               declare -a var:  1  1  1  0
               declare -A var:  1  1  1  0
                    unset var:  1  1  1  1

Резюме

  • declare -p var &>/dev/null надежно (100%?) Для тестирования именованных переменных в Bash, начиная с версии 3.0.
  • [ -n "${var+x}" ] надежен в ситуациях, соответствующих POSIX, но не может обрабатывать массивы.
  • Существуют другие тесты для проверки, является ли переменная непустой, и для проверки объявленных переменных в других оболочках. Но эти тесты не подходят ни для скриптов Bash, ни для POSIX.
), а не определенных специальных переменных ($!, $@, $# , $, $*, $?, $-, [1134], $1, $2, ... и все, что я мог забыть). Поскольку ни один из них не является массивом, стиль POSIX [ -n "${var+x}" ] работает для всех этих специальных переменных. Но остерегайтесь оборачивать его в функцию, так как многие специальные переменные меняют значения / существование при вызове функций.

Замечание по совместимости оболочки

Если в вашем скрипте есть массивы, и вы пытаетесь сделать его совместимым с максимально возможным количеством оболочек, рассмотрите возможность использования typeset -p вместо declare -p. Я читал, что ksh поддерживает только первое, но не смог проверить это. Я знаю, что Bash 3.0+ и Zsh 5.5.1 поддерживают оба typeset -p и declare -p, отличающиеся только тем, что одно является альтернативой другому. Но я не проверял различия между этими двумя ключевыми словами и не проверял другие оболочки.

Если вам нужен ваш сценарий для совместимости с POSIX sh, вы не можете использовать массивы. Без массивов [ -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).

[111]

Код тестового примера

Обратите внимание, что результаты теста могут быть неожиданными из-за того, что Bash рассматривает индексы нечислового массива как «0», если переменная не была объявлена ​​как ассоциативный массив. Кроме того, ассоциативные массивы действительны только в Bash 4.0 +.

[112]

Тестовый вывод

Тестовая мнемоника в строке заголовка соответствует [ -n "$var" ], [ -n "${var+x}" ], [ "${#var[@]}" != 0 ] и declare -p var, соответственно.

[113]

Резюме

  • declare -p var &>/dev/null надежно (100%?) Для тестирования именованных переменных в Bash, начиная с версии 3.0.
  • [ -n "${var+x}" ] надежен в ситуациях, соответствующих POSIX, но не может обрабатывать массивы.
  • Существуют другие тесты для проверки, является ли переменная непустой, и для проверки объявленных переменных в других оболочках. Но эти тесты не подходят ни для скриптов Bash, ни для POSIX.
9
ответ дан Mark Haferkamp 7 September 2016 в 16:27
поделиться
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
21
ответ дан 22 November 2019 в 20:19
поделиться

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

function a {
        if [ ! -z "$1" ]; then
                echo '$1 is set'
        fi
}
4
ответ дан 22 November 2019 в 20:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: