Назад | Перейти на главную страницу

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

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

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

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

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

if [ -z "${VAR}" ];

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

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

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

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

if [[ $variable ]]

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

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

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

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

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

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

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

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

  • сброшен
  • установить в пустую строку
  • установить в непустую строку

В большинстве случаев вам нужно только знать, установлена ​​ли переменная в непустую строку, но иногда важно различать неустановленную и установленную на пустую строку.

Ниже приведены примеры того, как вы можете протестировать различные возможности, и это работает в 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 оператор, а не строка.

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

Еще один вариант, который я использовал, - установить переменную, но ее можно переопределить другой переменной, например

export PORT=${MY_PORT:-5432}

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

Если вас интересует различие между состояниями 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

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

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

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

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

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

В вопрос спрашивает как проверить, является ли переменная пустой строкой и на это уже даны лучшие ответы.
Но я приземлился здесь после того, как прошел период программирования на php, и на самом деле я искал проверку вроде пустая функция в php работает в оболочке bash.
Прочитав ответы, я понял, что неправильно думаю в bash, но, тем не менее, в тот момент функция вроде пустой в php было бы так удобно в моем коде на bash.
Поскольку я думаю, что это может случиться с другими, я решил преобразовать пустую функцию php в 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, любой, кто использует эту функцию, должен оценить этот риск и, возможно, решить отключить эти проверки, оставив только первый.

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

[ "$foo" ] && echo "foo is not empty"
[ "$foo" ] || echo "foo is indeed empty"

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

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

В этой строке будет установлено ЗНАЧЕНИЕ, если был предоставлен аргумент, и будет напечатано сообщение об ошибке с добавлением номера строки сценария в случае ошибки (и завершится выполнение сценария).

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

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

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

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

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

одноразовое расширение duffbeer703решение:

#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter

Не точный ответ, но наткнулся на эту уловку. Если строка, которую вы ищете, происходит от «команды», вы можете сохранить команду в env. переменной, а затем выполнять ее каждый раз для оператора if, скобки не требуются!

Например, эта команда, которая определяет, используете ли вы debian:

grep debian /proc/version

полный пример:

IS_DEBIAN="grep -i debian /proc/version"

if $IS_DEBIAN; then
  echo 'yes debian'
else
  echo 'non debian'
fi

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