使用函数测试未设置的Bash变量

Dav*_*veP 28 variables bash undefined

一个简单的Bash变量测试:

${varName:?    "${varName} is not defined"}
Run Code Online (Sandbox Code Playgroud)

我想把它放在一个函数中来重复使用它.怎么样?

以下失败

#
# Test a variable exists
tvar(){
 val=${1:?    "${1}    must be defined, preferably in $basedir"}
 if [ -z ${val}  ]
     then 
     echo Zero length value 
 else
     echo ${1} exists, value ${1}
 fi
}
Run Code Online (Sandbox Code Playgroud)

即如果测试失败,我需要退出.

Pau*_*ce. 46

感谢lhunath的回答,我被引导到了Bash man页面的一部分,我忽略了数百次:

    When  not performing substring  expansion, bash tests for a parameter that
    is unset  or null; omitting the colon results in a test only for a parame?
    ter that is unset.

这促使我创建以下真值表:


                | unset |   set    | set and  | meaning
                |       | but null | not null |
    ============+=======+==========+==========+=============================
     ${var-_}   |   T   |     F    |    T     | not null or not set
    ------------+-------+----------+----------+-----------------------------
     ${var:-_}  |   T   |     T    |    T     | always true, use for subst.
    ------------+-------+----------+----------+-----------------------------
     $var       |   F   |     F    |    T     | var is set and not null
    ------------+-------+----------+----------+-----------------------------
     ${!var[@]} |   F   |     T    |    T     | var is set

该表介绍了最后一行中的规范.Bash man页面显示"如果name不是数组,如果设置了name,则展开为0,否则为null." 出于这个真值表的目的,即使它是一个数组,它的行为也是一样的.


lhu*_*ath 19

你正在寻找的是间接的.

assertNotEmpty() {
    : "${!1:? "$1 is empty, aborting."}"
}
Run Code Online (Sandbox Code Playgroud)

如果您执行以下操作,则会导致脚本中止并显示错误消息:

$ foo=""
$ assertNotEmpty foo
bash: !1:  foo is empty, aborting.
Run Code Online (Sandbox Code Playgroud)

如果您只想测试是否foo为空,而不是中止脚本,请使用此代替函数:

[[ $foo ]]
Run Code Online (Sandbox Code Playgroud)

例如:

until read -p "What is your name? " name && [[ $name ]]; do
    echo "You didn't enter your name.  Please, try again." >&2
done
Run Code Online (Sandbox Code Playgroud)

另请注意,emptyunset参数之间存在非常重要的差异.你应该注意不要混淆这些条款!空参数是一个设置但只能设置为空字符串的参数.未设置的参数是根本不存在的参数.

前面的例子都测试了参数.如果要测试未设置的参数并考虑所有设置的参数,无论它们是否为空,请使用以下命令:

[[ ! $foo && ${foo-_} ]]
Run Code Online (Sandbox Code Playgroud)

在这样的函数中使用它:

assertIsSet() {
    [[ ! ${!1} && ${!1-_} ]] && {
        echo "$1 is not set, aborting." >&2
        exit 1
    }
}
Run Code Online (Sandbox Code Playgroud)

只有在您传递的参数名称表示未设置的参数时才会中止脚本:

$ ( foo="blah"; assertIsSet foo; echo "Still running." )
Still running.
$ ( foo=""; assertIsSet foo; echo "Still running." )
Still running.
$ ( unset foo; assertIsSet foo; echo "Still running." )
foo is not set, aborting.
Run Code Online (Sandbox Code Playgroud)


dno*_*zay 5

你想用 [ -z ${parameter+word} ]

部分内容man bash:

Parameter Expansion
    ...
    In  each  of  the cases below, word is subject to tilde expansion, parameter expansion, command substitution, and
    arithmetic expansion.  When not performing substring expansion, bash tests for a parameter that is unset or null;
    omitting the colon results in a test only for a parameter that is unset.
    ...
    ${parameter:+word}
           Use Alternate Value.  If parameter is null or unset, nothing is substituted, otherwise  the  expansion  of
           word is substituted.
    ...
Run Code Online (Sandbox Code Playgroud)

换一种说法:

    ${parameter+word}
           Use Alternate Value.  If parameter is unset, nothing is substituted, otherwise  the  expansion  of
           word is substituted.
Run Code Online (Sandbox Code Playgroud)

一些例子:

$ set | grep FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$ declare FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=1
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ unset FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$
Run Code Online (Sandbox Code Playgroud)


And*_*cia 1

即,如果测试失败我需要退出。

代码:

${varName:?    "${varName} is not defined"}
Run Code Online (Sandbox Code Playgroud)

当不存在名为“varName”的变量时,将返回非零退出代码。最后一个命令的退出代码保存在$?.

关于您的代码:

val=${1:?    "${1}    must be defined, preferably in $basedir"}
Run Code Online (Sandbox Code Playgroud)

也许它没有做你需要的事情。如果$1未定义,则将"${1}"不替换任何内容。也许您想使用字面上${1}不进行替换的单引号。

val=${1:?    '${1}    must be defined, preferably in $basedir'
Run Code Online (Sandbox Code Playgroud)