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

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

是否正确道路? (必须有些更简单的方法)

评论

请参阅:在StackOverflow上的Bash中测试非零长度的字符串。

在Bash中,[[-v VAR]]用于检查是否定义了VAR,[[-z $ VAR]]用于检查是否将“ $ VAR”扩展为空字符串(“”)。因此,您可以使用[[-v VAR && -z $ VAR]]。在此处阅读更多信息(带有官方参考)

#1 楼

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

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


评论


这是否包括变量IS SET的值是否为“”?

–布伦特
09年5月12日在18:25

是的,它确实...“ -z”测试零长度的字符串。

– David Z
09年5月13日在2:40

如果[! -z“ $ VAR”];

–亚伦·科普利
13年7月22日在17:26



如果[-n“ $ VAR”],则-z的倒数为-n;

–Felipe Alvarez
13-10-9在5:59

双引号确保变量不会拆分。命令行上的简单$ var将由空格分隔为参数列表,而“ $ var”始终仅是一个参数。经常给变量加引号是一种好习惯,它可以阻止您跳入包含空格的文件名(除其他外)。示例:执行a =“ x --help”之后,尝试使用cat $ a-它会为您提供cat的帮助页面。然后尝试使用cat“ $ a”-(通常)说cat:x --help:没有这样的文件或目录。简而言之,尽早报价并经常报价,您几乎永远不会后悔。

–Score_Under
2014年7月15日13:40

#2 楼

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

以下任意一种:

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”是任意的。 br />
如果您想知道变量是否为空但未设置,请执行以下操作:

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


评论


如果[[$ variable]]对我来说很好用,甚至不需要其他提议的解决方案之一所需要的set -u。

– Teemu Leisti
2012年9月14日15:14

我认为这比公认的答案更好。

– q
13年4月5日在10:00

为什么在建议使用非便携式功能时没有好处呢?

–阿拉斯泰尔·欧文(Alastair Irvine)
2014年11月24日上午8:16​​

@AlastairIrvine:我在回答的第一句话中提到了可移植性,问题标题和正文中包含“ Bash”一词,问题被标记为bash,双括号结构在许多方面都具有明显的优势。而且出于一致性和可维护性的原因,我不建议混合使用括号样式。如果您需要最大,最低的公分母可移植性,请使用sh代替Bash。如果您需要它提供的增强功能,请使用Bash并充分使用它。

–丹尼斯·威廉姆森
2014年11月24日13:59

@BrunoBronosky:我还原了编辑。不需要;在最后。然后可以在下一行完全不使用分号。

–丹尼斯·威廉姆森
16-11-30在23:52

#3 楼

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


unset
设置为空字符串
设置为非字符串-空字符串

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

以下是如何测试各种可能性的示例,它可以在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+foo}构造扩展为空字符串如果未设置VAR,或者如果foo设置为任何值(包括空字符串),则设置为VAR

${VAR-foo}构造函数扩展为VAR的值(包括设置为空字符串),并扩展为foo未设定。这对于提供用户可覆盖的默认值很有用(例如,除非变量${COLOR-red}设置为q43,否则red表示要使用COLOR)。

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

评论


也可以使用[-z“ $ {VAR-set}”]来测试设置为空字符串的变量。

–nwellnhof
13年5月17日在17:56

@nwellnhof:谢谢!我更新了答案,以使用更简短的语法。

–理查德·汉森(Richard Hansen)
13年5月18日在18:00

第一个和最后一个构造有什么区别?它们都对应于“ VAR未设置或设置为非空字符串”。

– Faheem Mitha
13年7月22日在8:53

@FaheemMitha:这不是你的错-我的答案很难看。我添加了一个表格,希望可以使答案更加清楚。

–理查德·汉森(Richard Hansen)
13年7月22日在17:10

未设置的检查不可靠。如果用户在bash中调用set -u或set -o名词集,则测试将仅导致错误“ bash:VAR:未绑定变量”。有关更可靠的未设置检查,请参见stackoverflow.com/a/13864829。我的检查变量是否为null或未设置是[-z“ $ {VAR:-}”]。我检查变量是否为非空为[“ $ {VAR:-}”]。

–金凯文
17年9月14日在14:12

#4 楼

-z是最好的方法。

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

export PORT=${MY_PORT:-5432}


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

评论


今天偶然发现了这个,这正是我想要的。谢谢!在某些脚本中,我必须容忍set -o nounset。

–opello
2012-02-16 23:58



#5 楼

如果您有兴趣区分空置状态和未设置状态,请查看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


#6 楼

我见过[ -z "$foo" ]的另一种替代方法,但是我不确定为什么人们会使用这种方法,有人知道吗?

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


无论如何,如果您不允许取消设置变量(通过set -uset -o nounset),那么这两种方法都会遇到麻烦。有一个简单的解决方法:

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


注意:这将使您的变量未定义。

评论


在pubs.opengroup.org/onlinepubs/009695399/utilities/test.html上有关于-z替代项的评论。基本上,它并不打算替代-z。相反,它处理$ foo可以扩展为以[或测试引起混淆的元字符]开头的情况。在开始时放置任意的非元字符可以消除这种可能性。

–詹姆斯·斯诺格(James Sneeringer)
2011年12月9日19:15

#7 楼

该问题询问如何检查变量是否为空字符串,并且已经给出了最佳答案。
但是经过一段时间的php编程后,我进入了这里,而我实际上搜索的是像空一样的检查在bash外壳中工作的php中的函数。
读完答案后,我意识到我在bash中的想法不正确,但是无论如何,在那时,像php中的empty这样的函数在我的bash代码中会非常方便。 />由于我认为这可能会发生在其他人身上,因此我决定在bash中转换php empty函数。
根据php手册:如果变量不存在或者其值是以下:


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

当然,null和false情况不能在bash中转换,因此将其省略。

function empty
{
    local var=""

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

评论


在函数里面为空-为什么写[[$(echo“ 1”)]];返回,而不是简单地返回1?

–多尔
16-09-28在19:33

#8 楼

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

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


评论


如果foo只包含空格,那将失败

–布赖恩
2010年5月20日在21:16

如果foo以破折号开头,则在某些shell中也会失败,因为foo被解释为选项。例如。在solaris ksh上,zsh和bash没问题,sh和/ bin / test将失败

–ktf
2011年10月20日在7:40

#9 楼

我的5美分:还有比if ...短的语法,这是这样的:

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


如果提供了参数,则此行将设置VALUE,并且将显示错误消息

可以在abs指南中找到另一个示例(搜索«Example 10-7»)。 br />

#10 楼

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

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


#11 楼

个人更喜欢更清晰的检查方法:

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


评论


一些外壳不接受双等号。

–丹尼斯·威廉姆森
2012年2月25日在12:19

问题是关于bash。我正在使用bash。对我来说效果很好。您到底在说什么?

– Fedir RYKHTIK
2012-2-25在13:03

如果您使用的是Bash,则应使用双方括号。对于那些可能阅读您的答案并使用其他Shell的人,我之前的评论是一个简单的事实陈述。

–丹尼斯·威廉姆森
2012年2月25日15:49

在这种情况下,可以使用单个方括号,请参阅serverfault.com/questions/52034/…

–卢卡·鲍里昂(Luca Borrione)
2012年8月31日19:21

#12 楼

duffbeer703解决方案的oneliner扩展:

#! /bin/bash
[ -z "" ] || some_command_that_needs__parameter


#13 楼

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


所以这就像一种间接方法(每次都运行它)来检查一个空字符串(它恰好正在检查命令的错误响应,但是它也恰好返回一个空字符串)字符串)。