it-swarm.cn

如何确定bash变量是否为空?

确定bash中的变量是否为空(“”)的最佳方法是什么?

我听说建议我做if [ "x$variable" = "x" ]

那是正确方法吗? (必须有一些更简单的方法)

784
Brent

如果未设置或将变量设置为空字符串(“”),则返回true。

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

在Bash中,当您不关心不支持它的shell的可移植性时,应始终使用双括号语法:

以下任何一项:

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

在Bash中,使用双方括号不需要引号。您可以简化变量does包含以下值的测试:

if [[ $variable ]]

该语法与ksh兼容(无论如何至少与ksh93兼容)。在纯POSIX或更旧的Bourne外壳(例如sh或破折号)中不起作用。

请参阅 我在这里的答案BashFAQ/031 ,以了解有关双方括号和单方括号之间差异的更多信息。

您可以测试以查看是否明确未设置变量(与空字符串不同):

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

其中“ x”是任意的。

如果您想知道变量是否为null而不是未设置:

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

Bash(和任何POSIX兼容Shell)中的变量可以处于以下三种状态之一:

  • 未设定
  • 设置为空字符串
  • 设置为非空字符串

大多数时候,您只需要知道变量是否设置为非空字符串,但是偶尔区分未设置和设置为空字符串很重要。

以下是如何测试各种可能性的示例,它可以在bash或任何POSIX兼容Shell中运行:

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,则${VAR+foo}构造将扩展为空字符串;如果将foo设置为任何值(包括空字符串),则${VAR-foo}构造将扩展为VAR

${COLOR-red}构造扩展为VAR(如果已设置(包括设置为空字符串))和foo(如果未设置)的值。这对于提供用户可覆盖的默认值很有用(例如[ x"${VAR}" = x ]说要使用red,除非已将变量COLOR设置为某值)。

通常建议使用[来测试变量是未设置还是设置为空字符串的原因是因为-n命令(也称为test)的某些实现有错误。如果VAR设置为[ "${VAR}" = "" ],则某些实现在给定[时会做错事情,因为-n的第一个参数被错误地解释为_ [SOME_CODE] ] _运算符,而不是字符串。

239
Richard Hansen

-z是最好的方法。

我使用的另一个选项是设置一个变量,但是它可以被另一个变量覆盖,例如

export PORT=${MY_PORT:-5432}

如果$MY_PORT变量为空,然后将PORT设置为5432,否则将PORT设置为MY_PORT。注意语法包括冒号和破折号。

38
Rory

如果您有兴趣区分空置状态和未设置状态,请查看bash的-u选项:

$ 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 Shell中工作的检查。
看完答案后,我意识到我在bash中使用时不正确,但是在那一刻,像php中的empty这样的函数在我的bash代码中非常方便。
由于我认为这可能会发生在其他人身上,因此我决定在bash中转换php空函数

根据 php手册
如果变量不存在或值等于以下值之一,则认为该变量为空:

  • “”(空字符串)
  • 0 (0 as an integer)
  • 0.0(0为浮点数)
  • “ 0”(0作为字符串)
  • 空数组
  • 声明的变量,但没有值

当然nullfalse情况无法在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



Demo:
以下代码段:

#!/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逻辑中,此功能对零的检查可能会导致副作用,恕我直言,使用此功能的任何人都应该评估这种风险,并可能决定取消那些检查,仅保留第一个检查。

6
Luca Borrione

我的5美分:语法也比if ..., 这个:

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

如果提供了参数,则此行将设置VALUE,并在出现错误的情况下显示一条以脚本行号开头的错误消息(并终止脚本执行)。

可以在 abs-guide 中找到另一个示例(搜索《示例10-7》)。

5
gluk47

整个if-then和-z都是不必要的。

 [“ $ foo”] &&回显“ foo不为空” 
 [“ $ foo”] ||回显“ foo确实为空” 
5
namewithoutwords

确实在$ FOO设置为空时正确:

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

duffbeer7 的解决方案的oneliner扩展:

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

没有确切的答案,但是遇到了这个窍门。如果您要查找的字符串来自“命令”,那么您实际上可以将命令存储在环境中。变量,然后每次对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