Как определить, пуста ли переменная bash?
Каков наилучший способ определить, является ли переменная в bash пустой ("")?
Я слышал, что мне рекомендуется if [ "x$variable" = "x" ]
Это правильный способ? (должно быть что-то более прямолинейное)
12 ответов
Это вернет true, если переменная не установлена или установлена в пустую строку ("").
if [ -z "$VAR" ];
В 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} ]]
, где «x» произвольно.
Если вы хотите узнать, является ли переменная нулевой, но не отменяется:
if [[ -z $variable && ${variable+x} ]]
Переменная в 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
, а не строка.
-z
- лучший способ.
Другими параметрами, которые я использовал, является установка переменной, но ее можно переопределить другой переменной, например
export PORT=${MY_PORT:-5432}
Если переменная $MY_PORT
пуста, то PORT
устанавливается значение 5432, в противном случае для параметра PORT установлено значение 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, и то, что я на самом деле искал, было проверкой, как функция empty в php , работающая в оболочке bash.
После прочтения ответов я понял, что я не думал правильно в bash, но так или иначе в этот момент функция, подобная empty в php, была бы очень удобной в моем коде bash.
Как я думаю, это может случиться с другими, я решил преобразовать функцию php empty в bash
В соответствии с руководством по php :
переменная считается пустым, если он не существует или его значение является одним из следующих:
- "" (пустая строка)
- 0 (0 как целое число)
- 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, любой, кто использует эту функцию, должен оценить этот риск и, возможно, решит сократить эти проверки, оставив только первый.
Лично предпочитайте более четкий способ проверки:
if [ "${VARIABLE}" == "" ]; then
echo VARIABLE is empty
else
echo VARIABLE is not empty
fi
Мои 5 центов: есть более короткий синтаксис, чем if ...
, этот:
VALUE="${1?"Usage: $0 value"}"
В этой строке будет установлено значение VALUE, если аргумент предоставлен, и выведет сообщение об ошибке, добавленное с номером строки сценария, в случае ошибки (и завершит выполнение скрипта).
Другой пример можно найти в abs-guide (найдите «Пример 10-7»).
расширение oneliner решение duffbeer703 :
#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter