Вопрос: Как определить, пуста ли переменная bash?


Каков наилучший способ определить, является ли переменная в bash пустой ("")?

Я слышал, что мне рекомендуется if [ "x$variable" = "x" ]

Это верный путь? (должно быть что-то более прямолинейное)


700
2018-05-12 17:54


Источник




Ответы:


Это вернет true, если переменная не установлена ​​или установлена ​​в пустую строку ("").

if [ -z "$VAR" ];

958
2018-05-12 18:06



Включает ли это, если переменная IS SET соответствует значению ""? - Brent
Да, это ... «-z» проверяет строку нулевой длины. - David Z
if [ ! -z "$VAR" ]; - Aaron Copley
обратная -z является -n  if [ -n "$VAR" ]; - Felipe Alvarez
Двойные кавычки гарантируют, что переменная не будет разделена. Просто $var в командной строке будут разделены пробелом в список параметров, в то время как "$var" всегда будет только одним параметром. Котировка переменных часто является хорошей практикой и не позволяет вам отключиться от имен файлов, содержащих пробелы (среди прочего). Пример: после a="x --help", пытаться cat $a - он предоставит вам страницу справки для cat, Затем попробуйте cat "$a"- он будет (обычно) сказать cat: x --help: No such file or directory, Короче говоря, цитируйте рано и часто цитируйте, и вы почти никогда не пожалеете об этом. - Score_Under


В Bash, когда вы не заботитесь о переносимости оболочек, которые его не поддерживают, вы всегда должны использовать синтаксис с двойной привязкой:

Любое из следующего:

if [[ -z $variable ]]
if [[ -z "$variable" ]]
if [[ ! $variable ]]
if [[ ! "$variable" ]]

В Bash, используя двойные квадратные скобки, цитаты не нужны. Вы можете упростить тест для переменной, которая делает содержат значение:

if [[ $variable ]]

Этот синтаксис совместим с ksh (по крайней мере, ksh93, во всяком случае). Он не работает в чистых POSIX или более старых оболочках Bourne, таких как sh или тире.

Видеть мой ответ здесь а также BashFAQ / 031 для получения дополнительной информации о различиях между двойными и одиночными квадратными скобками.

Вы можете проверить, не отличается ли переменная (в отличие от пустой строки):

if [[ -z ${variable+x} ]]

где «х» произвольно.

Если вы хотите узнать, является ли переменная нулевой, но не отменяется:

if [[ -z $variable && ${variable+x} ]]

222
2018-02-25 03:37



Что if [[ $variable ]] работал отлично для меня, и даже не нуждался в set -u который требовался одним из других предлагаемых решений. - Teemu Leisti
Я думаю, что это лучше, чем принятый ответ. - qed
Почему вы рекомендуете непереносимую функцию, если это не дает никакой пользы? - Alastair Irvine
@AlastairIrvine: я упоминаю переносимость в первом предложении моего ответа, заголовок вопроса и тело содержат слово «Bash», и вопрос помечен удар, а структура двойной скобки обеспечивает явные преимущества во многих отношениях. И я не рекомендую смешивать стили скобок по соображениям последовательности и ремонтопригодности. Если вам нужна максимальная, самая низкая общая переносимость знаменателя, используйте sh вместо Баша. Если вам нужны расширенные возможности, которые он предоставляет, используйте Bash и используйте его полностью. - Dennis Williamson
@BrunoBronosky: Я вернул редактирование. Нет требования для ; в конце. then может быть на следующей строке без точки с запятой. - Dennis Williamson


Переменная в bash (и любая совместимая с POSIX оболочка) может находиться в одном из трех состояний:

  • снята с охраны
  • установить на пустую строку
  • установить непустую строку

Большую часть времени вам нужно только знать, установлена ​​ли переменная в непустую строку, но иногда важно различать unset и set to the empty string.

Ниже приведены примеры того, как вы можете тестировать различные возможности, и работает в bash или любой совместимой с POSIX оболочке:

if [ -z "${VAR}" ]; then
    echo "VAR is unset or set to the empty string"
fi
if [ -z "${VAR+set}" ]; then
    echo "VAR is unset"
fi
if [ -z "${VAR-unset}" ]; then
    echo "VAR is set to the empty string"
fi
if [ -n "${VAR}" ]; then
    echo "VAR is set to a non-empty string"
fi
if [ -n "${VAR+set}" ]; then
    echo "VAR is set, possibly to the empty string"
fi
if [ -n "${VAR-unset}" ]; then
    echo "VAR is either unset or set to a non-empty string"
fi

Вот то же самое, но в удобной форме таблицы:

                        +-------+-------+-----------+
                VAR is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [ -z "${VAR}" ]       | true  | true  | false     |
| [ -z "${VAR+set}" ]   | true  | false | false     |
| [ -z "${VAR-unset}" ] | false | true  | false     |
| [ -n "${VAR}" ]       | false | false | true      |
| [ -n "${VAR+set}" ]   | false | true  | true      |
| [ -n "${VAR-unset}" ] | true  | false | true      |
+-----------------------+-------+-------+-----------+

${VAR+foo} Конструкция расширяется до пустой строки, если VAR не работает или foo если VAR устанавливается на что угодно (включая пустую строку).

${VAR-foo} конструкции расширяется до значения VAR если установлено (в том числе установлено пустую строку) и foo если не установлено. Это полезно для предоставления пользовательских значений по умолчанию (например, ${COLOR-red} говорит использовать red если переменная COLOR было установлено что-то).

Причина почему [ x"${VAR}" = x ] часто рекомендуется для проверки того, является ли переменная отключена или установлена ​​в пустую строку, потому что некоторые реализации [ команда (также известная как test) являются ошибками. Если VAR задано как-то вроде -n, то некоторые реализации будут делать не то, что [ "${VAR}" = "" ] потому что первый аргумент [ ошибочно интерпретируется как -n оператор, а не строка.


202
2018-04-24 20:39



Тестирование переменной, заданной пустой строкой, также может быть выполнено с использованием [ -z "${VAR-set}" ], - nwellnhof
@nwellnhof: Спасибо! Я обновил свой ответ, чтобы использовать более короткий синтаксис. - Richard Hansen
@FaheemMitha: Это не твоя вина - мой ответ был трудным для чтения. Я добавил таблицу, чтобы надеяться сделать ответ более ясным. - Richard Hansen
@RichardHansen: Спасибо, это полезное дополнение. - Faheem Mitha
Неисправленные проверки не являются надежными. Если пользователь вызвал set -u или set -o nounset в bash, тогда тест просто приведет к ошибке «bash: VAR: unbound variable». Видеть stackoverflow.com/a/13864829 для более надежной проверки. Моя проверка проверки того, является ли переменная нулевой или не установлена, [ -z "${VAR:-}" ], Моя проверка того, является ли переменная непустой, [ "${VAR:-}" ], - Kevin Jin


-z это лучший способ.

Другими параметрами, которые я использовал, является установка переменной, но она может быть переопределена другой переменной, например

export PORT=${MY_PORT:-5432}

Если $MY_PORT переменная пуста, тогда PORT получает значение 5432, в противном случае для параметра PORT установлено значение MY_PORT, Обратите внимание, что синтаксис включает двоеточие и тире.


35
2018-06-11 13:19



Случайно нашел это сегодня, и это было именно то, что я хотел. Благодаря! Я должен терпеть set -o nounset в некоторых сценариях. - opello


Если вам интересно различать случаи состояния set-empty или unset, посмотрите на параметр -u для bash:

$ set -u
$ echo $BAR
bash: BAR: unbound variable
$ [ -z "$BAR" ] && echo true
bash: BAR: unbound variable
$ BAR=""
$ echo $BAR

$ [ -z "$BAR" ] && echo true
true

25
2018-05-12 18:21





Альтернатива, которую я видел [ -z "$foo" ] является следующим, однако я не уверен, почему люди используют этот метод, кто-нибудь знает?

[ "x${foo}" = "x" ]

В любом случае, если вы отказываетесь от неустановленных переменных (либо set -u или set -o nounset), тогда у вас возникнут проблемы с обоими из этих методов. Это простое решение:

[ -z "${foo:-}" ]

Примечание: это оставит вашу переменную undef.


9
2017-10-20 03:58



Есть комментарий об альтернативе -z в pubs.opengroup.org/onlinepubs/009695399/utilities/test.html, В принципе, он не должен быть альтернативой -z, Скорее, он обрабатывает случаи, когда $foo может расширяться до чего-то, начинающегося с метасимвола, который [ или test были бы смущены. Включение произвольного неметахарактера вначале устраняет эту возможность. - James Sneeringer


вопрос спрашивает как проверить, является ли переменная пустой строкой и для этого уже даны наилучшие ответы.
Но я приземлился здесь после того, как прошло время программирования на php, и то, что я действительно искал, было проверкой, как пустая функция в php работая в оболочке bash.
Прочитав ответы, я понял, что я не думаю об этом правильно в bash, но так или иначе в этот момент функция вроде пустой в php было бы очень удобно в моем коде bash.
Поскольку я думаю, что это может случиться с другими, я решил преобразовать функцию php empty в bash

Согласно Руководство пользователя php:
переменная считается пустой, если она не существует или ее значение является одним из следующих:

  • "" (пустая строка)
  • 0 (0 как целое число)
  • 0.0 (0 в качестве поплавка)
  • «0» (0 в виде строки)
  • пустой массив
  • объявленная переменная, но без значения

Конечно, ноль а также ложный случаи не могут быть преобразованы в bash, поэтому они опущены.

function empty
{
    local var="$1"

    # Return true if:
    # 1.    var is a null string ("" as empty string)
    # 2.    a non set variable is passed
    # 3.    a declared variable or array but without a value is passed
    # 4.    an empty array is passed
    if test -z "$var"
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is zero (0 as an integer or "0" as a string)
    elif [ "$var" == 0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is 0.0 (0 as a float)
    elif [ "$var" == 0.0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return
    fi

    [[ $( echo "" ) ]]
}



Пример использования:

if empty "${var}"
    then
        echo "empty"
    else
        echo "not empty"
fi



Демо-версия:
следующий фрагмент:

#!/bin/bash

vars=(
    ""
    0
    0.0
    "0"
    1
    "string"
    " "
)

for (( i=0; i<${#vars[@]}; i++ ))
do
    var="${vars[$i]}"

    if empty "${var}"
        then
            what="empty"
        else
            what="not empty"
    fi
    echo "VAR \"$var\" is $what"
done

exit

выходы:

VAR "" is empty
VAR "0" is empty
VAR "0.0" is empty
VAR "0" is empty
VAR "1" is not empty
VAR "string" is not empty
VAR " " is not empty

Сказав, что в логике bash проверки на ноль в этой функции могут вызвать побочные проблемы imho, любой, кто использует эту функцию, должен оценить этот риск и, возможно, решит сократить эти проверки, оставив только первый.


7
2017-08-31 20:11



Внутри функции empty - почему ты написал [[ $( echo "1" ) ]] ; return вместо просто return 1 ? - Dor


все if-then и -z не нужны.

["$ foo"] && echo "foo не пуст"
["$ foo"] || echo "foo действительно пуст"

6
2018-01-26 14:02



Это не удастся, если foo содержит только пробелы - Brian
Также не удастся выполнить некоторые оболочки, если Foo начинается с тире, поскольку он интерпретируется как опция. Например. по солнечной энергии КШ, ЗШ а также удар не проблема, ш а также / Бен / тест не удастся - ktf


Это верно, когда $ FOO установлен и пуст:

[ "${FOO+x}" = x ] && [ -z "$FOO" ]

5
2018-05-20 20:52





Лично предпочитайте более четкий способ проверки:

if [ "${VARIABLE}" == "" ]; then
  echo VARIABLE is empty
else
  echo VARIABLE is not empty
fi

5
2017-12-09 15:15



Некоторые оболочки не принимают знак двойного равенства. - Dennis Williamson
Вопрос был о bash. Я использую bash. Хорошо работает для меня. О чем именно вы говорите? - Fedir RYKHTIK
Если вы используете Bash, вы должны использовать двойные квадратные скобки. Мой предыдущий комментарий был простой инструкцией для тех, кто мог бы прочитать ваш ответ и использовать другую оболочку. - Dennis Williamson
единичные квадратные скобки в этом случае в порядке, см. serverfault.com/questions/52034/... - Luca Borrione


Мои 5 центов: есть более короткий синтаксис, чем if ..., вот этот:

VALUE="${1?"Usage: $0 value"}"

Эта строка будет устанавливать значение VALUE, если аргумент был предоставлен, и будет печатать сообщение об ошибке, добавленное с номером строки сценария, в случае ошибки (и прекратит выполнение скрипта).

Другой пример можно найти в абс-гид (найдите «Пример 10-7»).


4
2017-11-09 16:46