Variables Posix外壳:区分空变量和不存在的变量

Variables Posix外壳:区分空变量和不存在的变量,variables,posix,sh,Variables,Posix,Sh,在纯/bin/sh中,如何区分空变量、未设置变量和不存在(未定义)变量 情况如下: # Case 1: not existing echo "${foo}" # Case 2: unset foo= echo "${foo}" # Case 3: Empty foo="" echo "${foo}" 现在我想检查这三个案例中的每一个。 如果案例2和案例3实际上是相同的,那么我必须至少能够区分它们和案例1 有什么想法吗 更新 多亏了Matteo 下面是代码的外观: #foo <--

在纯
/bin/sh
中,如何区分空变量、未设置变量和不存在(未定义)变量

情况如下:

# Case 1: not existing
echo "${foo}"

# Case 2: unset
foo=
echo "${foo}"

# Case 3: Empty
foo=""
echo "${foo}"
现在我想检查这三个案例中的每一个。 如果案例2和案例3实际上是相同的,那么我必须至少能够区分它们和案例1

有什么想法吗

更新 多亏了Matteo

下面是代码的外观:

#foo  <-- not defined
bar1=
bar2=""
bar3="a"

if ! set | grep '^foo=' >/dev/null 2>&1; then
    echo "foo does not exist"
elif [ -z "${foo}" ]; then
    echo "foo is empty"
else
    echo "foo has a value"
fi

if ! set | grep '^bar1=' >/dev/null 2>&1; then
    echo "bar1 does not exist"
elif [ -z "${bar1}" ]; then
    echo "bar1 is empty"
else
    echo "bar1 has a value"
fi

if ! set | grep '^bar2=' >/dev/null 2>&1; then
    echo "bar2 does not exist"
elif [ -z "${bar2}" ]; then
    echo "bar2 is empty"
else
    echo "bar2 has a value"
fi


if ! set | grep '^bar3=' >/dev/null 2>&1; then
    echo "bar3 does not exist"
elif [ -z "${bar3}" ]; then
    echo "bar3 is empty"
else
    echo "bar3 has a value"
fi
你可以用

如果未指定选项或参数,set应在当前语言环境的排序规则序列中写入所有shell变量的名称和值。每个名称应以单独的行开始,格式如下:

您可以列出所有变量(
set
),并为要检查的变量名设置grep

set | grep '^foo='

我不知道
sh
,但是在
bash
dash
中,您可以对案例1和案例2/3执行
echo${TEST:?Error}
。从快速浏览来看,它似乎也应该适用于伯恩壳牌公司

您可以在bash和dash中这样使用它(使用$?获取错误代码)


如果var未设置,则可以使用${var?}语法抛出错误;如果var未设置或为空,则可以使用${var:?}语法抛出错误。举个具体例子:

$ unset foo
$ test -z "${foo?unset}" && echo foo is empty || echo foo is set to $foo
-bash: foo: unset
$ foo=
$ test -z "${foo?unset}" && echo foo is empty || echo foo is set to $foo
foo is empty
$ foo=bar
$ test -z "${foo?unset}" && echo foo is empty || echo foo is set to $foo
foo is set to bar

语法是POSIX,但它不会区分不存在的变量和空变量variable@Matteo我想使用
$?
来编写案例脚本,请参见我的编辑。
${TEST:?Error}
不区分未定义和空<代码>${TEST?Error}确实如此。您的案例2和案例3是相同的
foo=
定义foo为空字符串的方式与
foo=”“
完全相同。
函数foo=bar{:;}
将在bash中愚弄它,而
bar=$'\nfoo=nope'
将在大多数其他shell中愚弄它。
echo ${TEST:?"Error"}
bash: TEST: Error
[lf@dell:~/tmp/soTest] echo $?
1
[lf@dell:~/tmp/soTest] TEST2="ok"
[lf@dell:~/tmp/soTest] echo ${TEST2:?"Error"}
ok
[lf@dell:~/tmp/soTest] echo $?
0
[lf@dell:~/tmp/soTest] dash
$ echo ${TEST3:?"Error"}       
dash: 1: TEST3: Error
$ TEST3=ok
$ echo ${TEST3:?"Error"}
ok
$ unset foo
$ test -z "${foo?unset}" && echo foo is empty || echo foo is set to $foo
-bash: foo: unset
$ foo=
$ test -z "${foo?unset}" && echo foo is empty || echo foo is set to $foo
foo is empty
$ foo=bar
$ test -z "${foo?unset}" && echo foo is empty || echo foo is set to $foo
foo is set to bar