如何判断一个string是不是在bash shell脚本中定义的?
如果我想检查空string,我会做的
[ -z $mystr ]
但是如果我想检查variables是否被定义了呢? 或者是没有区分bash脚本?
我认为你以后的答案暗示了(如果没有说明的话) 温科的答案 ,尽pipe这不是简单的解释。 为了区分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
您可能可以将第二行的两个testing合并为一个:
if [ -z "$VAR" -a "${VAR+xxx}" = "xxx" ]; then echo VAR is set but empty; fi
但是,如果您阅读Autoconf的文档,则会发现他们不build议将术语与“ -a
”相结合,并build议使用单独的简单testing与&&
结合使用。 我还没遇到一个有问题的系统。 这并不意味着他们以前不存在(但是他们现在可能非常罕见,即使他们在遥远的过去并不稀罕)。
您可以在Bash手册中find这些的详细信息,以及其他相关的shell参数扩展 , test
或[
命令和条件expression式 。
最近我通过电子邮件询问了这个问题的答案:
你使用两个testing,我理解第二个,但不是第一个。 更确切地说,我不了解可变扩展的需要
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
公平的问题 – 答案是“不,你简单的select不会做同样的事情”。
假设我在testing之前写下这个:
VAR=
你的testing会说“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
在第二对testing中,variables被设置,但它被设置为空值。 这是${VAR=value}
和${VAR:=value}
符号的区别。 对于${VAR-value}
和${VAR:-value}
以及${VAR+value}
和${VAR:+value}
等等,同样如此。
正如Gili在他的回答中指出的那样,如果使用set -o nounset
选项运行bash
,那么上面的基本答案会失败,并显示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 +u
( set -u
等同于set -o nounset
)来取消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也适用于未定义的variables。 要区分一个未定义的和已定义的,你可以使用这里列出的东西,或者更清楚的解释。
最干净的方式就是在这些例子中使用扩展。 要获得所有选项,请检查手册的参数扩展部分。
备用字:
~$ 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。 参数replace:
- $ {var + blahblah}:如果var被定义,则用'blahblah'代替expression式,否则null被replace
- $ {var-blahblah}:如果var被定义,它本身被replace,否则'blahblah'被replace
- $ {var?blahblah}:如果var被定义,则被replace,否则该函数以'blahblah'作为错误信息存在。
根据您的程序逻辑是否定义variables$ mystr,您可以执行以下操作:
isdefined=0 ${mystr+ export isdefined=1}
现在,如果isdefined = 0,那么variables是未定义的,如果isdefined = 1,则variables被定义
这种检查variables的方式比上面的答案要好,因为它更优雅,更易读,而且如果你的bash shell被configuration为使用未定义variables(set -u)
,那么脚本将提前终止。
其他有用的东西:
如果它是未定义的,则将默认值7分配给$ mystr,否则保持原样:
mystr=${mystr- 7}
如果variables未定义,则打印出错信息并退出函数:
: ${mystr? not defined}
在这里注意我使用了':',以免定义$ mystr的内容作为命令执行。
testing的总结。
[ -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
检查被定义variables的显式方法是:
[ -v mystr ]
另一种select: “列表数组索引”扩展 :
$ unset foo $ foo= $ echo ${!foo[*]} 0 $ foo=bar $ echo ${!foo[*]} 0 $ foo=(bar baz) $ echo ${!foo[*]} 0 1
这个扩展到空string的唯一时间是当foo
未被设置,所以你可以用string条件来检查它:
$ 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
是你可以添加到脚本的顶部的东西,如果在脚本的任何地方没有声明variables的话,这将会出错。 您将看到的消息是unbound variable
,但正如其他人提到的,它不会捕获空string或空值。 为了确保任何单独的值不为空,我们可以testing一个variables,因为它是用${mystr:?}
扩展的,也就是美元符号扩展,这个parameter null or not set
。
Bash参考手册是有关bash信息的权威来源。
下面是一个testingvariables的例子,看它是否存在:
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
我能够使用快速正则expression式在vim中自动化:
s/\vexport ([A-Z_]+)\=("[^"]+")\n/if [ -z "$\1" ]; then\r export \1=\2\rfi\r/gc
这可以通过直观地select相关行来应用,然后键入:
。 命令栏预填充:'<,'>
。 粘贴上面的命令,然后回车。
testingVim的这个版本:
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Aug 22 2015 15:38:58) Compiled by root@apple.com
Windows用户可能需要不同的行结束符。
这是我认为是一个更清晰的方式来检查是否定义了一个variables:
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
调用集没有任何参数..它输出所有的variables定义..
列表中的最后一个将是你的脚本中定义的那些。
所以你可以通过pipe道输出来找出什么东西是被定义的,什么不是