如果我要检查空字符串我会做
[ -z $mystr ]
但如果我要检查是否变量都被定义? 或者有没有在bash脚本没有区别?
如果我要检查空字符串我会做
[ -z $mystr ]
但如果我要检查是否变量都被定义? 或者有没有在bash脚本没有区别?
我觉得你是以后的答案是隐含的(如果不说)由Vinko的答案 ,虽然它没有说出来简单。 为了区分VAR是否被设置,但空或没有设置,你可以使用:
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
if [ -z "$VAR" ] && [ "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
你也许可以在第二行的两个测试组合成一个具有:
if [ -z "$VAR" -a "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
但是,如果你阅读的Autoconf的文档,你会发现,他们不建议用“相结合方面-a
”,并使用单独的简单测试联合做推荐&&
。 我还没有遇到一个系统,其中有一个问题; 这并不意味着他们没有使用存在(但他们很可能是极为罕见的,这些天,即使他们不是在遥远的过去罕见)。
你可以找到这些细节,以及其他相关的外壳参数扩展 ,在test
或[
命令和条件表达式在Bash的手册。
我最近通过电子邮件询问这个答案的问题:
您可以使用两个测试,我的理解,第二个好,但不是第一个。 更确切地说,我不理解变量扩展的需要
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
这是不是完成相同的?
if [ -z "${VAR}" ]; then echo VAR is not set at all; fi
公平的问题 - 答案是:“不,你更简单的替代不会做同样的事情。”
假设我测试之前写:
VAR=
您的测试会说:“VAR没有设置在所有”,但我会说(通过暗示,因为它呼应什么)“VAR设置,但其价值可能是空的”。 试试这个脚本:
(
unset VAR
if [ -z "${VAR+xxx}" ]; then echo JL:1 VAR is not set at all; fi
if [ -z "${VAR}" ]; then echo MP:1 VAR is not set at all; fi
VAR=
if [ -z "${VAR+xxx}" ]; then echo JL:2 VAR is not set at all; fi
if [ -z "${VAR}" ]; then echo MP:2 VAR is not set at all; fi
)
输出是:
JL:1 VAR is not set at all
MP:1 VAR is not set at all
MP:2 VAR is not set at all
在第二对测试中,变量设置,但是它被设置为空值。 这就是区别${VAR=value}
和${VAR:=value}
符号做。 同上,用于${VAR-value}
和${VAR:-value}
和${VAR+value}
和${VAR:+value}
,依此类推。
作为吉利在他指出的答案 ,如果您运行bash
与set -o nounset
选项,那么基本的答案上述失败, unbound variable
。 这是很容易纠正:
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
if [ -z "${VAR-}" ] && [ "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
或者,你可以取消该set -o nounset
与选项set +u
( set -u
等同于set -o nounset
)。
~> if [ -z $FOO ]; then echo "EMPTY"; fi
EMPTY
~> FOO=""
~> if [ -z $FOO ]; then echo "EMPTY"; fi
EMPTY
~> FOO="a"
~> if [ -z $FOO ]; then echo "EMPTY"; fi
~>
-z工程未定义的变量太多。 未定义和区分定义的,你会用列出的东西在这里或者,更清晰的解释, 在这里 。
干净的方式是使用扩大像在这些实施例。 为了让所有的选择检查手册的参数扩展部分。
替代字:
~$ unset FOO
~$ if test ${FOO+defined}; then echo "DEFINED"; fi
~$ FOO=""
~$ if test ${FOO+defined}; then echo "DEFINED"; fi
DEFINED
默认值:
~$ FOO=""
~$ if test "${FOO-default value}" ; then echo "UNDEFINED"; fi
~$ unset FOO
~$ if test "${FOO-default value}" ; then echo "UNDEFINED"; fi
UNDEFINED
当然,你会使用这些不同的一个,把你想要的,而不是“默认值”的值,并直接使用扩展,如果合适的话。
高级Bash脚本编程指南,10.2。 参数换人:
立足程序逻辑的变量$ myStr中是否定义或没有,你可以做到以下几点:
isdefined=0
${mystr+ export isdefined=1}
现在,如果isdefined = 0,则变量是未定义的,如果isdefined = 1定义的变量
检查变量的这种方式比上面的回答更好,因为它是更优雅,可读的,如果你的bash shell的配置为错误的使用未定义的变量(set -u)
该脚本将提前终止。
其他有用的东西:
有分配到$ myStr中,如果它是未定义的7的默认值,并使其保持完好,否则:
mystr=${mystr- 7}
打印的错误信息,并且如果所述变量未定义退出功能:
: ${mystr? not defined}
当心这里,我用“:”以免有作为的情况下,它被定义的命令执行$ myStr中的内容。
测试总结。
[ -n "$var" ] && echo "var is set and not empty"
[ -z "$var" ] && echo "var is unset or empty"
[ "${var+x}" = "x" ] && echo "var is set" # may or may not be empty
[ -n "${var+x}" ] && echo "var is set" # may or may not be empty
[ -z "${var+x}" ] && echo "var is unset"
[ -z "${var-x}" ] && echo "var is set and empty"
https://stackoverflow.com/a/9824943/14731包含一个更好的答案(一说是更具可读性,并与工作set -o nounset
启用)。 它的工作原理大致是这样的:
if [ -n "${VAR-}" ]; then
echo "VAR is set and is not empty"
elif [ "${VAR+DEFINED_BUT_EMPTY}" = "DEFINED_BUT_EMPTY" ]; then
echo "VAR is set, but empty"
else
echo "VAR is not set"
fi
显式的检查方法定义是一个变量的存在:
[ -v mystr ]
另一种选择: 在“列表数组的下标”扩展 :
$ unset foo
$ foo=
$ echo ${!foo[*]}
0
$ foo=bar
$ echo ${!foo[*]}
0
$ foo=(bar baz)
$ echo ${!foo[*]}
0 1
这个扩展为空字符串的唯一时间是当foo
没有设置,这样你就可以用字符串有条件的检查:
$ unset foo
$ [[ ${!foo[*]} ]]; echo $?
1
$ foo=
$ [[ ${!foo[*]} ]]; echo $?
0
$ foo=bar
$ [[ ${!foo[*]} ]]; echo $?
0
$ foo=(bar baz)
$ [[ ${!foo[*]} ]]; echo $?
0
应该在任何的bash版本是可用> = 3.0
不要进一步摆脱这种自行车,但想补充
shopt -s -o nounset
是你可以添加到脚本的顶部,如果变量不是在脚本中任何宣布将错误。 你会看到该消息是unbound variable
,但其他人提到它不会赶上一个空字符串或空值。 为了确保任何单个值不为空,因为它与扩大,我们可以测试一个变量${mystr:?}
又称美元符号扩展,这将具有错误parameter null or not set
。
的击参考手册是约bash的信息的权威来源。
下面是测试一个变量看,如果它存在的一个例子:
if [ -z "$PS1" ]; then
echo This shell is not interactive
else
echo This shell is interactive
fi
(从节6.3.2 。)
需要注意的是后开的空白[
和前]
不是可选的 。
提示的Vim用户
我有一个脚本,有几个声明如下:
export VARIABLE_NAME="$SOME_OTHER_VARIABLE/path-part"
但我希望他们推迟到任何现有值。 所以我重新写了他们看起来像这样:
if [ -z "$VARIABLE_NAME" ]; then
export VARIABLE_NAME="$SOME_OTHER_VARIABLE/path-part"
fi
我能够在使用快速正则表达式VIM自动完成:
s/\vexport ([A-Z_]+)\=("[^"]+")\n/if [ -z "$\1" ]; then\r export \1=\2\rfi\r/gc
这可以通过肉眼选择相关的行,然后键入应用:
。 命令栏预填充具有:'<,'>
粘贴在上面的命令并回车。
测试在这个版本的Vim:
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Aug 22 2015 15:38:58)
Compiled by root@apple.com
Windows用户可能需要不同的行尾。
以下是我认为是来检查变量定义更清晰的方式:
var_defined() {
local var_name=$1
set | grep "^${var_name}=" 1>/dev/null
return $?
}
按如下方式使用它:
if var_defined foo; then
echo "foo is defined"
else
echo "foo is not defined"
fi
呼叫建立不带任何参数..它输出定义的所有瓦尔..
名单上的最后的将是你的脚本中定义的..
所以,你可以管其输出的东西,可以找出事情的定义和什么不