it-swarm-ru.tech

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

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

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

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

784
Brent

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

if [ -z "$VAR" ];
1075
duffbeer703

В 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} ]]
253
Paused until further notice.

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

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

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

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

239
Richard Hansen

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

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

export PORT=${MY_PORT:-5432}

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

38
Rory

Если вы заинтересованы в различении случаев пустого набора и незаданного состояния, посмотрите параметр -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
24
MikeyB

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

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

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

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

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

8
errant.info

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

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

  • "" (пустая строка)
  • 0 (0 as an integer)
  • 0.0 (0 как число с плавающей запятой)
  • "0" (0 как строка)
  • пустой массив
  • объявленная переменная, но без значения

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

6
Luca Borrione

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

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

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

Другой пример можно найти в abs-guide (поиск "Пример 10-7").

5
gluk47

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

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

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

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

расширение oneliner решения duffbeer7 :

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

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

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

Не точный ответ, но наткнулся на этот трюк. Если искомая строка взята из "команды", вы можете сохранить команду в 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

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

0
rogerdpack