关于shell:如何检查bash中是否设置了变量?

 2019-04-28 

How to check if a variable is set in Bash?

如何知道bash中是否设置了变量?

例如,如何检查用户是否为函数提供了第一个参数?

1
2
3
function a {
    # if $1 is set ?
}


(通常)正确的方法

1
if [ -z ${var+x} ]; then echo"var is unset"; else echo"var is set to '$var'"; fi

其中,${var+x}是一个参数扩展,如果var未设置,则该参数扩展值为零,否则替换字符串x

引号偏离

引号可以省略(因此我们可以称为${var+x}而不是"${var+x}",因为这种语法和用法保证它只会扩展到不需要引号的内容(因为它要么扩展到x(不包含换行符,因此不需要引号),要么不扩展到任何内容(导致[ -z ],这很方便计算结果与[ -z"" ]的值(真)相同)。

然而,尽管可以安全地省略引号,而且并非所有人都能立即察觉到(这个引号解释的第一作者,也是一个主要的bash编码人员,甚至不太清楚),但有时最好用[ -z"${var+x}" ]的引号编写解决方案,但速度惩罚的可能成本很小。第一位作者还将其添加为代码旁边的注释,使用此解决方案提供了此答案的URL,现在还包括对可以安全省略引号的原因的解释。

(经常)错误的方式

1
if [ -z"$var" ]; then echo"var is blank"; else echo"var is set to '$var'"; fi

这通常是错误的,因为它不区分未设置的变量和设置为空字符串的变量。也就是说,如果var='',那么上面的解决方案将输出"var为空"。

在用户必须指定扩展名或附加属性列表的情况下,取消设置和"设置为空字符串"之间的区别非常重要,如果不指定扩展名或附加属性列表,则默认为非空值,而指定空字符串应使脚本使用空扩展名或附加属性列表。

不过,这种区别在每一种情况下都不一定是必要的。在这种情况下,[ -z"$var" ]就可以了。


要检查非空/非零字符串变量,即如果设置了,请使用

1
if [ -n"$1" ]

它与-z相反。我发现自己使用-n-z多。

您可以这样使用它:

1
2
3
4
5
if [ -n"$1" ]; then
  echo"You supplied the first parameter!"
else
  echo"First parameter not supplied."
fi


以下是如何测试参数是未设置,还是为空("空")或设置为值:

1
2
3
4
5
6
7
8
9
10
11
12
13
+--------------------+----------------------+-----------------+-----------------+
|                    |       parameter      |     parameter   |    parameter    |
|                    |   Set and Not Null   |   Set But Null  |      Unset      |
+--------------------+----------------------+-----------------+-----------------+
| ${parameter:-word} | substitute parameter | substitute word | substitute word |
| ${parameter-word}  | substitute parameter | substitute null | substitute word |
| ${parameter:=word} | substitute parameter | assign word     | assign word     |
| ${parameter=word}  | substitute parameter | substitute null | assign word     |
| ${parameter:?word} | substitute parameter | error, exit     | error, exit     |
| ${parameter?word}  | substitute parameter | substitute null | error, exit     |
| ${parameter:+word} | substitute word      | substitute null | substitute null |
| ${parameter+word}  | substitute word      | substitute word | substitute null |
+--------------------+----------------------+-----------------+-----------------+

源:posix:参数扩展:

In all cases shown with"substitute", the expression is replaced with the value shown. In all cases shown with"assign", parameter is assigned that value, which also replaces the expression.


虽然这里描述的大多数技术都是正确的,但是bash 4.2支持对变量(man bash)的存在进行实际测试,而不是测试变量的值。

1
2
3
4
5
6
7
8
9
10
[[ -v foo ]]; echo $?
# 1

foo=bar
[[ -v foo ]]; echo $?
# 0

foo=""
[[ -v foo ]]; echo $?
# 0

值得注意的是,这种方法在用于检查set -u/set -o nounset模式中的未设置变量时不会导致错误,这与许多其他方法不同,例如使用[ -z模式。


有很多方法可以做到这一点,其中包括:

1
if [ -z"$1" ]

如果$1为空或未设置,则此操作成功


为了查看变量是否是非空的,我使用

1
if [[ $var ]]; then ...       # `$var' expands to a nonempty string

如果变量未设置或为空,则进行相反的测试:

1
if [[ ! $var ]]; then ...     # `$var' expands to the empty string (set or not)

为了查看是否设置了变量(空或非空),我使用

1
2
if [[ ${var+x} ]]; then ...   # `var' exists (empty or nonempty)
if [[ ${1+x} ]]; then ...     # Parameter 1 exists (empty or nonempty)

如果变量未设置,则进行相反的测试:

1
2
if [[ ! ${var+x} ]]; then ... # `var' is not set at all
if [[ ! ${1+x} ]]; then ...   # We were called with no arguments


我总是发现另一个答案中的posix表比较慢,所以下面是我的看法:

1
2
3
4
5
6
7
8
9
10
11
12
13
   +----------------------+------------+-----------------------+-----------------------+
   |   if VARIABLE is:    |    set     |         empty         |        unset          |
   +----------------------+------------+-----------------------+-----------------------+
 - |  ${VARIABLE-default} | $VARIABLE  |         ""           |      "default"       |
 = |  ${VARIABLE=default} | $VARIABLE  |         ""           | $(VARIABLE="default") |
 ? |  ${VARIABLE?default} | $VARIABLE  |         ""           |       exit 127        |
 + |  ${VARIABLE+default} |"default"  |      "default"       |         ""           |
   +----------------------+------------+-----------------------+-----------------------+
:- | ${VARIABLE:-default} | $VARIABLE  |      "default"       |      "default"       |
:= | ${VARIABLE:=default} | $VARIABLE  | $(VARIABLE="default") | $(VARIABLE="default") |
:? | ${VARIABLE:?default} | $VARIABLE  |       exit 127        |       exit 127        |
:+ | ${VARIABLE:+default} |"default"  |         ""           |         ""           |
   +----------------------+------------+-----------------------+-----------------------+

请注意,每个组(有冒号和没有冒号)都有相同的设置和未设置案例,因此唯一不同的是如何处理空案例。

对于前面的冒号,空的和未设置的案例是相同的,所以我会尽可能使用这些案例(即使用:=,而不仅仅是=,因为空的案例是不一致的)。

标题:

  • set表示VARIABLE为非空(VARIABLE="something")
  • 空是指VARIABLE为空/空(VARIABLE="")
  • "未结算"是指VARIABLE不存在(unset VARIABLE)

价值观:

  • $VARIABLE表示结果是变量的原值。
  • "default"表示结果是提供的替换字符串。
  • ""表示结果为空(空字符串)。
  • exit 127表示脚本停止执行,退出代码127。
  • $(VARIABLE="default")表示结果是变量的原始值,所提供的替换字符串被分配给变量以备将来使用。


在bash的现代版本上(我想是4.2或更高版本,我不确定),我会尝试以下方法:

1
2
3
4
5
6
7
8
9
if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigil
then
    echo"Variable is unset"
elif [ -z"$SOMEVARIABLE" ]
then
    echo"Variable is set to an empty string"
else
    echo"Variable is set to some string"
fi


1
2
3
4
5
if ["$1" !="" ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

尽管对于论点,通常最好测试$,我认为这是论点的数量。

1
2
3
4
5
if [ $# -gt 0 ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi


如果未设置,您想退出

这对我有用。如果没有设置参数,我希望脚本退出并显示一条错误消息。

1
2
3
4
5
6
#!/usr/bin/env bash

set -o errexit

# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"

当它运行时返回一个错误

1
2
peek@peek:~$ ./setver.sh
./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument

仅检查,不退出-空和未设置无效

如果只想检查值set=valid或unset/empty=invalid,请尝试此选项。

1
2
3
4
5
6
7
8
9
10
TSET="good val"
TEMPTY=""
unset TUNSET

if ["${TSET:-}" ]; then echo"VALID"; else echo"INVALID";fi
# VALID
if ["${TEMPTY:-}" ]; then echo"VALID"; else echo"INVALID";fi
# INVALID
if ["${TUNSET:-}" ]; then echo"VALID"; else echo"INVALID";fi
# INVALID

或者,即使是简短的测试;—)

1
2
3
["${TSET:-}"   ] && echo"VALID" || echo"INVALID"
["${TEMPTY:-}" ] && echo"VALID" || echo"INVALID"
["${TUNSET:-}" ] && echo"VALID" || echo"INVALID"

仅选中,不退出-仅空无效

这就是问题的答案。如果只想检查值set/empty=valid或unset=invalid,请使用此选项。

注意,..-1中的"1"不重要,它可以是任何东西(比如x)

1
2
3
4
5
6
7
8
9
10
TSET="good val"
TEMPTY=""
unset TUNSET

if ["${TSET+1}" ]; then echo"VALID"; else echo"INVALID";fi
# VALID
if ["${TEMPTY+1}" ]; then echo"VALID"; else echo"INVALID";fi
# VALID
if ["${TUNSET+1}" ]; then echo"VALID"; else echo"INVALID";fi
# INVALID

简短测试

1
2
3
["${TSET+1}"   ] && echo"VALID" || echo"INVALID"
["${TEMPTY+1}" ] && echo"VALID" || echo"INVALID"
["${TUNSET+1}" ] && echo"VALID" || echo"INVALID"

我将此答案献给@mklement0(评论),他要求我准确回答问题。

参考http://pubs.opengroup.org/onlinepubs/9699919799/utilities/v3_chap02.html tag_18_06_02


阅读bash手册页的"参数扩展"部分。参数扩展并不能为正在设置的变量提供一般的测试,但是如果参数没有设置,您可以对它做一些事情。

例如:

1
2
3
4
function a {
    first_arg=${1-foo}
    # rest of the function
}

如果指定,则将first_arg设置为$1,否则使用值"foo"。如果a绝对必须取单个参数,且不存在良好的默认值,则在没有给定参数时,可以退出并显示错误消息:

1
2
3
4
function a {
    : ${1?a must take a single argument}
    # rest of the function
}

(注意使用:作为一个空命令,它只扩展其参数的值。在这个例子中,我们不想对$1做任何事情,如果没有设置,就退出)


要检查变量是否设置为非空值,请使用[ -n"$x" ],其他人已经指出。

大多数情况下,最好将具有空值的变量视为未设置的变量。但如果需要,可以区分这两种情况:如果设置了x,则[ -n"${x+set}" ]("${x+set}")扩展到set,如果未设置x,则扩展到空字符串。

要检查参数是否已通过,测试$#,这是传递给函数(或脚本,而不是函数)的参数数(请参见Paul的答案)。


在bash中,您可以在[[ ]]内置中使用-v

1
2
3
4
5
6
7
#! /bin/bash -u

if [[ ! -v SOMEVAR ]]; then
    SOMEVAR='hello'
fi

echo $SOMEVAR

对于那些在使用set -u脚本时希望检查未设置或空的脚本:

1
2
3
4
if [ -z"${var-}" ]; then
   echo"Must provide var environment variable. Exiting...."
   exit 1
fi

如果set -u的话,常规的[ -z"$var" ]检查将失败,但是如果var未设置而没有失败,[ -z"${var-}" ]将扩展为空字符串。


注释

因为bash标签,我给出了一个重点关注bash的答案。

简短回答

只要您只处理bash中的命名变量,这个函数就应该总是告诉您是否设置了变量,即使它是一个空数组。

1
2
3
is-variable-set() {
    declare -p $1 &>dev/null
}

为什么会这样

在bash中(至少早于3.0),如果var是一个声明/设置变量,那么declare -p var输出一个declare命令,该命令将变量var设置为其当前类型和值,并返回状态代码0(success)。如果var未声明,则declare -p varstderr输出错误消息,并返回状态代码1。使用&>/dev/null,将常规stdoutstderr输出重定向到/dev/null,不会被看到,也不会更改状态代码。因此,函数只返回状态代码。

为什么其他方法(有时)在bash中失败

  • [ -n"$var" ]: This only checks if ${var[0]} is nonempty. (In Bash, $var is the same as ${var[0]}.)
  • [ -n"${var+x}" ]: This only checks if ${var[0]} is set.
  • ["${#var[@]}" != 0 ]: This only checks if at least one index of $var is set.

当这个方法在bash中失败时

这只适用于命名变量(包括$_),不适用于某些特殊变量($!$@$#$$$*$?$-$0$1$2…,以及任何我可能忘记的变量)。因为这些都不是数组,所以posix样式的[ -n"${var+x}" ]适用于所有这些特殊变量。但是要小心将它包装在一个函数中,因为许多特殊变量在调用函数时会改变值/存在性。

外壳兼容性说明

如果您的脚本有数组,并且您试图使其与尽可能多的shell兼容,那么考虑使用typeset -p而不是declare -p。我读到KSH只支持前者,但还没有测试过。我知道bash 3.0+和zsh 5.5.1都支持typeset -pdeclare -p,只是其中一个支持另一个。但我没有测试这两个关键字之外的差异,也没有测试其他shell。

如果您需要脚本与posix-sh兼容,那么就不能使用数组。没有阵列,[ -n"{$var+x}" ]就可以工作。

bash中不同方法的比较代码

此函数取消设置变量vareval是通过的代码,运行测试以确定var是否由evald代码设置,最后显示不同测试的结果状态代码。

我跳过了test -v var[ -v var ][[ -v var ]],因为它们产生的结果与posix标准[ -n"${var+x}" ]相同,但需要bash 4.2+。我也跳过了typeset -p,因为它和我测试过的外壳(bash 3.0到5.0和zsh 5.5.1)中的declare -p是一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
is-var-set-after() {
    # Set var by passed expression.
    unset var
    eval"$1"

    # Run the tests, in increasing order of accuracy.
    [ -n"$var" ] # (index 0 of) var is nonempty
    nonempty=$?
    [ -n"${var+x}" ] # (index 0 of) var is set, maybe empty
    plus=$?
    ["${#var[@]}" != 0 ] # var has at least one index set, maybe empty
    count=$?
    declare -p var &>/dev/null # var has been declared (any type)
    declared=$?

    # Show test results.
    printf '%30s: %2s %2s %2s %2s
'
"$1" $nonempty $plus $count $declared
}

测试用例代码

注意,如果变量没有声明为关联数组,那么测试结果可能是意外的,因为bash将非数字数组索引视为"0"。此外,关联数组仅在bash 4.0+中有效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Header.
printf '%30s: %2s %2s %2s %2s
'
"test" '-n' '+x' '#@' '-p'
# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an
# indexed array is also the nonindexed value, and non-numerical
# indices in an array not declared as associative are the same as
# index 0.
is-var-set-after"var=foo"                        #  0  0  0  0
is-var-set-after"var=(foo)"                      #  0  0  0  0
is-var-set-after"var=([0]=foo)"                  #  0  0  0  0
is-var-set-after"var=([x]=foo)"                  #  0  0  0  0
is-var-set-after"var=([y]=bar [x]=foo)"          #  0  0  0  0
# '[ -n"$var" ]' fails when var is empty.
is-var-set-after"var=''"                         #  1  0  0  0
is-var-set-after"var=([0]='')"                   #  1  0  0  0
# Indices other than 0 are not detected by '[ -n"$var" ]' or by
# '[ -n"${var+x}" ]'.
is-var-set-after"var=([1]='')"                   #  1  1  0  0
is-var-set-after"var=([1]=foo)"                  #  1  1  0  0
is-var-set-after"declare -A var; var=([x]=foo)"  #  1  1  0  0
# Empty arrays are only detected by 'declare -p'.
is-var-set-after"var=()"                         #  1  1  1  0
is-var-set-after"declare -a var"                 #  1  1  1  0
is-var-set-after"declare -A var"                 #  1  1  1  0
# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after"unset var"                      #  1  1  1  1

测试输出

标题行中的测试助记符分别对应于[ -n"$var" ][ -n"${var+x}" ]["${#var[@]}" != 0 ]declare -p var

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                         test: -n +x #@ -p
                      var=foo:  0  0  0  0
                    var=(foo):  0  0  0  0
                var=([0]=foo):  0  0  0  0
                var=([x]=foo):  0  0  0  0
        var=([y]=bar [x]=foo):  0  0  0  0
                       var='':  1  0  0  0
                 var=([0]=''):  1  0  0  0
                 var=([1]=''):  1  1  0  0
                var=([1]=foo):  1  1  0  0
declare -A var; var=([x]=foo):  1  1  0  0
                       var=():  1  1  1  0
               declare -a var:  1  1  1  0
               declare -A var:  1  1  1  0
                    unset var:  1  1  1  1

总结

  • declare -p var &>/dev/null is (100%?) reliable for testing named variables in Bash since at least 3.0.
  • [ -n"${var+x}" ] is reliable in POSIX compliant situations, but cannot handle arrays.
  • Other tests exist for checking if a variable is nonempty, and for checking for declared variables in other shells. But these tests are suited for neither Bash nor POSIX scripts.


你可以做到:

1
2
3
4
5
function a {
        if [ ! -z"$1" ]; then
                echo '$1 is set'
        fi
}


当启用bash选项set -u时,上述答案不起作用。此外,它们不是动态的,例如,如何测试名为"dummy"的变量?试试这个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
is_var_defined()
{
    if [ $# -ne 1 ]
    then
        echo"Expected exactly one argument: variable name as string, e.g., 'my_var'"
        exit 1
    fi
    # Tricky.  Since Bash option 'set -u' may be enabled, we cannot directly test if a variable
    # is defined with this construct: [ ! -z"$var" ].  Instead, we must use default value
    # substitution with this construct: [ ! -z"${var:-}" ].  Normally, a default value follows the
    # operator ':-', but here we leave it blank for empty (null) string.  Finally, we need to
    # substitute the text from $1 as 'var'.  This is not allowed directly in Bash with this
    # construct: [ ! -z"${$1:-}" ].  We need to use indirection with eval operator.
    # Example: $1="var"
    # Expansion for eval operator:"[ ! -z \${$1:-} ]" ->"[ ! -z \${var:-} ]"
    # Code  execute: [ ! -z ${var:-} ]
    eval"[ ! -z \${$1:-} ]"
    return $?  # Pedantic.
}

相关:在bash中,如何测试变量是否以"-u"模式定义


使用[[ -z"$var" ]]是了解变量是否已设置的最简单方法,但该选项-z不区分未设置的变量和设置为空字符串的变量:

1
2
3
4
5
$ set=''
$ [[ -z"$set" ]] && echo"Set" || echo"Unset"
Unset
$ [[ -z"$unset" ]] && echo"Set" || echo"Unset"
Unset

最好根据变量类型进行检查:env变量、参数或正则变量。

对于env变量:

1
[[ $(env | grep"varname=" | wc -l) -eq 1 ]] && echo"Set" || echo"Unset"

对于参数(例如,检查参数$5是否存在):

1
[[ $# -ge 5 ]] && echo"Set" || echo"Unset"

对于常规变量(使用辅助函数,以优雅的方式执行):

1
2
3
4
function declare_var {
   declare -p"$1" &> /dev/null
}
declare_var"var_name" && echo"Set" || echo"Unset"

笔记:

  • $#: gives you the number of positional parameters.
  • declare -p: gives you the definition of the variable passed as a parameter. If it exists, returns 0, if not, returns 1 and prints an error message.
  • &> /dev/null: suppresses output from declare -p without affecting its return code.

在shell中,可以使用-z运算符,如果字符串长度为零,则为真。

一个简单的一行程序,用于设置默认的MY_VAR,如果没有设置默认的MY_VAR,否则您可以选择显示以下消息:

1
2
[[ -z"$MY_VAR" ]] && MY_VAR="default"
[[ -z"$MY_VAR" ]] && MY_VAR="default" || echo"Variable already set."


我最喜欢的方式是:

1
2
3
4
5
6
$var=10
$if ! ${var+false};then echo"is set";else echo"NOT set";fi
is set
$unset var
$if ! ${var+false};then echo"is set";else echo"NOT set";fi
NOT set

因此,基本上,如果设置了一个变量,它将成为"对结果false的否定"(将是true的值)。

如果未设置,则将变成"对生成的true的否定"(空结果评估为true)(因此将结束为false="未设置")。


如果您想检查$@中的任何内容,我发现了一个更好的代码来执行此操作。

1
2
3
4
5
6
if [[ $1 ="" ]]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi

为什么这一切?$@中的所有内容都存在于bash中,但默认情况下它是空白的,因此test -ztest -n无法帮助您。

更新:还可以计算参数中的字符数。

1
2
3
4
5
6
if [ ${#1} = 0 ]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi


1
2
3
4
5
6
7
8
9
if [[ ${1:+isset} ]]
then echo"It was set and not null.">&2
else echo"It was not set or it was null.">&2
fi

if [[ ${1+isset} ]]
then echo"It was set but might be null.">&2
else echo"It was was not set.">&2
fi


1
[[ $foo ]]

1
(( ${#foo} ))

1
let ${#foo}

1
declare -p foo

这是我每天使用的:

1
2
3
4
5
6
7
8
#
# Check if a variable is set
#   param1  name of the variable
#
function is_set()
{
    [[ -n"${1}" ]] && test -n"$(eval"echo"\${${1}+x}"")"
}

这在Linux和Solaris下非常适用,直到bash 3.0。

1
2
3
4
5
6
7
8
9
bash-3.00$ myvar="TEST"
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ mavar=""
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ unset myvar
bash-3.00$ is_set myvar ; echo $?
1


1
if [[ ${!xx[@]} ]] ; then echo xx is defined; fi


我喜欢辅助功能来隐藏bash的原始细节。在这种情况下,这样做会增加更多(隐藏的)粗糙度:

1
2
3
4
5
6
7
# The first ! negates the result (can't use -n to achieve this)
# the second ! expands the content of varname (can't do ${$varname})
function IsDeclared_Tricky
{
  local varname="$1"
  ! [ -z ${!varname+x} ]
}

因为我第一次在这个实现中有错误(受到Jens和Lionel的回答的启发),所以我想出了一个不同的解决方案:

1
2
3
4
5
# Ask for the properties of the variable - fails if not declared
function IsDeclared()
{
  declare -p $1 &>/dev/null
}

我发现它更直接,更害羞,更容易理解/记忆。测试用例显示它是等效的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function main()
{
  declare -i xyz
  local foo
  local bar=
  local baz=''

  IsDeclared_Tricky xyz; echo"IsDeclared_Tricky xyz: $?"
  IsDeclared_Tricky foo; echo"IsDeclared_Tricky foo: $?"
  IsDeclared_Tricky bar; echo"IsDeclared_Tricky bar: $?"
  IsDeclared_Tricky baz; echo"IsDeclared_Tricky baz: $?"

  IsDeclared xyz; echo"IsDeclared xyz: $?"
  IsDeclared foo; echo"IsDeclared foo: $?"
  IsDeclared bar; echo"IsDeclared bar: $?"
  IsDeclared baz; echo"IsDeclared baz: $?"
}

main

测试用例还显示local var不声明var(除非后面跟着"="。有相当一段时间我以为我是这样声明变量的,只是为了发现现在我只是表达了我的意图…我想这是不允许的。

IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
IsDeclared_Tricky bar: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz: 1
IsDeclared foo: 1
IsDeclared bar: 0
IsDeclared baz: 0

奖金:使用

我主要使用这个测试以某种"优雅"和安全的方式(几乎类似于一个接口…)为函数提供(和返回)参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#auxiliary functions
function die()
{
  echo"Error: $1"; exit 1
}

function assertVariableDeclared()
{
  IsDeclared"$1" || die"variable not declared: $1"
}

function expectVariables()
{
  while (( $# > 0 )); do
    assertVariableDeclared $1; shift
  done
}

# actual example
function exampleFunction()
{
  expectVariables inputStr outputStr
  outputStr="$inputStr world!"
}

function bonus()
{
  local inputStr='Hello'
  local outputStr= # remove this to trigger error
  exampleFunction
  echo $outputStr
}

bonus

如果用all调用,则需要声明变量:

Hello world!

其他:

Error: variable not declared: outputStr


我总是使用这个代码,因为任何第一次看到代码的人都很容易理解它:

1
2
3
4
if ["$variable" ="" ]
    then
    echo"Variable X is empty"
fi

如果想检查是否为空;

1
2
3
4
if [ !"$variable" ="" ]
    then
    echo"Variable X is not empty"
fi

就是这样。


如果要测试变量是绑定的还是未绑定的,即使在打开nounset选项之后,这也能很好地工作:

1
2
3
4
5
6
7
set -o noun set

if printenv variableName >/dev/null; then
    # variable is bound to a value
else
    # variable is unbound
fi


用于检查变量是否已声明/未设置的函数包括空的EDOCX1[0]

以下函数测试给定名称是否作为变量存在

1
2
3
4
5
6
7
8
9
10
# The first parameter needs to be the name of the variable to be checked.
# (See example below)

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;}
}
  • 通过首先测试变量是否已设置(un),如果不需要,可以避免调用declare。
  • 但是,如果$1包含空$array=()的名称,则调用declare将确保获得正确的结果。
  • 从未有太多数据传递给/dev/null,因为只有在变量未设置或数组为空时才调用declare。

该功能将在以下条件下进行测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
a;       # is not declared
a=;      # is declared
a="foo"; # is declared
a=();    # is declared
a=("");  # is declared
unset a; # is not declared

a;       # is unset
a=;      # is not unset
a="foo"; # is not unset
a=();    # is not unset
a=("");  # is not unset
unset a; # is unset

.

For more details

and a test script see my answer to the question"How do I check if a variable exists in bash?".

Remark: The similar usage of declare -p, as it is also shown by Peregring-lk's answer, is truly coincidental. Otherwise I would of course have credited it!


检查是否设置了变量

1
var=""; [[ $var ]] && echo"set" || echo"not set"


1
2
3
4
case"$1" in
"") echo"blank";;
 *) echo"set"
esac