如何检查是否在 Bash 中设置了变量

问:

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

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

function a {
    # if $1 is set ?
}

答1:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

(通常)正确的方式

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

其中 ${var+x} 是一个 parameter expansion,如果 var 未设置,则计算结果为空,否则替换字符串 x。

行情题外话

引号可以省略(所以我们可以说 v a r + x 而不是 " {var+x} 而不是 " var+x而不是"{var+x}"),因为这种语法 &使用保证这只会扩展为不需要引号的内容(因为它要么扩展为 x(不包含分词,因此不需要引号),要么不扩展(导致 [ -z ],它方便地计算为与 [ -z “” ] 相同的值(true)))。

然而,虽然引号可以安全地省略,而且对所有人都不是很明显(对于同时也是主要 Bash 编码器的 the first author of this quotes explanation 来说甚至不明显),但有时最好将带有引号的解决方案编写为 { 2},以 O(1) 速度损失的非常小的可能成本。第一作者还在使用此解决方案的代码旁边添加了此注释,提供了此答案的 URL,现在还包括解释为什么可以安全地省略引号。

(经常)错误的方式

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

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

在用户必须指定扩展名或附加属性列表并且不指定它们默认为非空值的情况下,未设置和“设置为空字符串”之间的区别是必不可少的,而指定空字符串应该使脚本使用空扩展名或附加属性列表。

但是,这种区别可能并非在每种情况下都必不可少。在这些情况下,[ -z “$var” ] 就可以了。

@Garrett,您的编辑使这个答案不正确,${var+x} 是正确的替代品。使用 [ -z ${var:+x} ] 产生的结果与 [ -z "$var" ] 没有什么不同。

这行不通。无论 var 是否设置为一个值,我都会得到“未设置”(用“unset var”清除,“echo $var”不产生输出)。

对于解决方案的语法 ${parameter+word},官方手册部分是 gnu.org/software/bash/manual/… ;但是,其中的一个错误是,它没有很清楚地提到此语法,而只是说引号(省略冒号[“:”]会导致仅对未设置的参数进行测试。.. ${parameter:+word} [意思]如果参数为null或未设置,则不替换任何内容,否则替换单词的扩展。);引用的参考文献 pubs.opengroup.org/onlinepubs/9699919799/utilities/…(很高兴知道)在这里有更清晰的文档。

当您使用多个表达式时,似乎需要引号,例如 [ -z "" -a -z ${var+x} ] 在 bash 4.3-ubuntu 中得到 bash: [: argument expected(但不是例如 zsh)。我真的不喜欢使用在某些情况下碰巧起作用的语法的答案。

使用简单的 [ -z $var ] 并不比省略引号更“错误”。无论哪种方式,您都在对您的输入做出假设。如果您可以将空字符串视为未设置,则只需 [ -z $var ]。

答2:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

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

if [ -n "$1" ]

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

你会像这样使用它:

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

我通常更喜欢 [[ ]] 而不是 [ ],因为 [[ ]] 更强大并且在某些情况下导致的问题更少(请参阅 this question 以了解两者之间的区别)。该问题专门要求 bash 解决方案并且没有提及任何可移植性要求。

问题是如何查看是否设置了变量。那么你不能假设变量已设置。

我同意,[] 特别适用于 shell(非 bash)脚本。

请注意,-n 是默认测试,因此更简单的 [ "$1" ] 或 [[ $1 ]] 也可以工作。另请注意,使用 [[ ]] quoting is unnecessary。

似乎它不是真的相反......真正的相反是if [ ! -z "$1" ]

答3:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

以下是如何测试参数是否未设置、为空(“Null”)或设置了值:

+--------------------+----------------------+-----------------+-----------------+
|   Expression       |       parameter      |     parameter   |    parameter    |
|   in script:       |   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: Parameter Expansion:

在所有用“替代”显示的情况下,表达式都被替换为显示的值。在所有用“assign”显示的情况下,参数都被分配了那个值,它也替换了表达式。

要在行动中展示这一点:

+--------------------+----------------------+-----------------+-----------------+
|   Expression       |  When FOO="world"    |  When FOO=""    |    unset FOO    |
|   in script:       |  (Set and Not Null)  |  (Set But Null) |     (Unset)     |
+--------------------+----------------------+-----------------+-----------------+
| ${FOO:-hello}      | world                | hello           | hello           |
| ${FOO-hello}       | world                | ""              | hello           |
| ${FOO:=hello}      | world                | FOO=hello       | FOO=hello       |
| ${FOO=hello}       | world                | ""              | FOO=hello       |
| ${FOO:?hello}      | world                | error, exit     | error, exit     |
| ${FOO?hello}       | world                | ""              | error, exit     |
| ${FOO:+hello}      | hello                | ""              | ""              |
| ${FOO+hello}       | hello                | hello           | ""              |
+--------------------+----------------------+-----------------+-----------------+

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

@HelloGoodbye 是的,它确实有效:set foo; echo ${1:-set but null or unset} echos "foo"; set --; echo ${1:-set but null or unset} 回显设置但为空...

@HelloGoodbye 位置参数可以用,呃,set :-)

这个答案非常令人困惑。有关如何使用此表的任何实际示例?

@BenDavis POSIX 标准的链接中解释了详细信息,该标准引用了该表所来自的章节。我在编写的几乎所有脚本中使用的一种构造是 : ${FOOBAR:=/etc/foobar.conf},用于为未设置或为空的变量设置默认值。

parameter 是任何变量名。 word 是一些要替换的字符串,具体取决于您使用的表中的语法,以及变量 $parameter 是设置、设置但为空还是未设置。不要让事情变得更复杂,但 word 也可以包含变量!这对于传递由字符分隔的可选参数非常有用。例如:${parameter:+,${parameter}} 如果设置但不为空,则输出逗号分隔的 ,$parameter。在这种情况下,word 是 ,${parameter}

答4:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

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

[[ -v foo ]]; echo $?
# 1

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

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

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

huntsbot.com – 高效赚钱,自由工作

在 bash 4.1.2 中,无论是否设置变量,[[ -v aaa ]]; echo $? ==>; -bash: conditional binary operator expected -bash: syntax error near 'aaa'

bash 4.2 中添加了 'test' 内置函数的 '-v' 参数。

添加了 -v 参数作为 -u shell 选项(名词集)的补充。打开'nounset' (set -u),如果不是交互式的,shell 将返回一个错误并终止。 $# 非常适合检查位置参数。但是,命名变量需要其他方式,而不是破坏,将它们标识为未设置。不幸的是,这个功能来得太晚了,因为许多人注定要兼容早期版本,在这种情况下他们不能使用它。唯一的其他选择是使用技巧或“黑客”来绕过它,如上所示,但这是最不雅的。

这就是为什么我在接受/最高投票的答案之后继续阅读。

这是标量的正确方法,并且在 ksh 中也可用。注意:如果您不想浪费半个小时盯着屏幕想知道发生了什么,它是 [[ -v foo ]] 而不是 [[ -v $foo ]]。除了验证它是否已设置之外,您通常还会寻找一个特定的值,例如 123。在这种情况下,我更喜欢使用 [[ ${foo-123} -eq 123 ]] 来压缩 [[ -v foo && $foo -eq 123 ]]

答5:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

有很多方法可以做到这一点,以下是其中之一:

if [ -z "$1" ]

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

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

未设置的参数和具有空值的参数之间存在差异。

我只是想学究一下,并指出这是与问题提出的相反的答案。问题询问是否设置了变量,而不是是否未设置变量。

[[ ]] 只不过是一个可移植性陷阱。此处应使用 if [ -n "$1" ]。

这个答案是不正确的。该问题要求一种方法来判断变量是否已设置,而不是是否设置为非空值。给定 foo="",$foo 有一个值,但 -z 只会报告它是空的。如果你有 set -o nounset,-z $foo 会爆炸。

这取决于“变量已设置”的定义。如果要检查变量是否设置为 非零 字符串,则 mbranning answer 是正确的。但是如果要检查变量是否已声明但未初始化(即foo=),那么Russel's answer 是正确的。

答6:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

我总是发现 other answer 中的 POSIX 表很难理解,所以这是我的看法:

参数扩展 VARIABLE set VARIABLE empty VARIABLE 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 退出 127 退出 127 ${VARIABLE:+default} “default” “” “”

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

对于前面的冒号,empty 和 unset 情况是相同的,所以我会尽可能使用它们(即使用 :=,而不仅仅是 =,因为空情况不一致)。

标题:

set 表示 VARIABLE 非空 (VARIABLE=“something”)

empty 表示 VARIABLE 为空/null (VARIABLE=“”)

unset 表示 VARIABLE 不存在(未设置 VARIABLE)

价值观:

$VARIABLE 表示结果是变量的原始值。

“默认”表示结果是提供的替换字符串。

“” 表示结果为 null(空字符串)。

exit 127 表示脚本停止执行,退出代码为 127。

$(VARIABLE=“default”) 表示结果为“default”,并且 VARIABLE(以前为空或未设置)也将设置为“default”。

您只修复了实际编码错误(使用变量时不需要的间接实例)。我进行了编辑以修复更多美元在解释描述方面产生影响的情况。顺便说一句,所有 shell 变量(数组除外)都是字符串变量;它们可能恰好包含一个可以解释为数字的字符串。谈论字符串只会模糊信息。引号与字符串无关,它们只是转义的替代方法。 VARIABLE="" 可以写成 VARIABLE=。不过,前者更具可读性。

感谢表格非常有用,但是如果未设置或为空,我试图让脚本退出。但我得到的退出代码是 1 而不是 127。

当 VARIABLE 未设置时,我看到 A=${VARIABLE=default} 的 A 等于 "default",而不是 VARIABLE 的原始值(未设置)。您对 $(VARIABLE="default") 的描述是否正确?也许我误读了您所说的原始价值的意思。

根据 documentation,它表示“在所有情况下,应替换参数的最终值”。因此,也许应该将描述更改为:$(VARIABLE="default") 表示结果为 "default",并且 VARIABLE 也将设置为等于 "default"。

使用新 table feature 的候选者。

答7:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

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

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

相反的测试变量是否未设置或为空:

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

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

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

相反的测试变量是否未设置:

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

我也已经使用了一段时间了;只是以简化的方式:[ $isMac ] && param="--enable-shared"

@Bhaskar 我认为这是因为 this answer 几乎在半年前就已经提供了基本相同的答案(使用 ${variable+x} 来获得 x 如果 $variable 已设置)。它还有更多详细信息解释了为什么它是正确的。

答8:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

笔记

由于 bash 标记,我给出了一个非常注重 Bash 的答案。

简短的回答

只要你在 Bash 中只处理命名变量,这个函数应该总是告诉你变量是否已经被设置,即使它是一个空数组。

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

为什么这有效

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

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

-n “$var” ]:这只检查 v a r [ 0 ] 是否为非空。(在 B a s h 中, {var[0]} 是否为非空。 (在 Bash 中, var[0]是否为非空。(在Bash中,var 与 v a r [ 0 ] 相同。) [ − n " {var[0]} 相同。) [ -n " var[0]相同。)[n"{var+x}" ]:这只检查是否设置了 v a r [ 0 ] 。 [ " {var[0]}。 [ " var[0]["{#var[@]}" != 0 ]: 这仅检查是否设置了至少一个 $var 索引。

当此方法在 Bash 中失败时

这仅适用于命名变量(包括 ) ,不适用于某些特殊变量( _),不适用于某些特殊变量( ,不适用于某些特殊变量(!、 @ 、 @、 @#、$ 、 、 *、 ? 、 ?、 ?-、$0、 $1、 2 、 . . . 以及我可能忘记的任何内容)。由于这些都不是数组,因此 P O S I X 风格的 [ − n " 2、...以及我可能忘记的任何内容)。由于这些都不是数组,因此 POSIX 风格的 [ -n " 2...以及我可能忘记的任何内容)。由于这些都不是数组,因此POSIX风格的[n"{var+x}" ] 适用于所有这些特殊变量。但请注意将其包装在函数中,因为许多特殊变量在调用函数时会更改值/存在。

外壳兼容性说明

如果您的脚本有数组并且您试图使其与尽可能多的 shell 兼容,那么请考虑使用 typeset -p 而不是 declare -p。我读过 ksh 只支持前者,但无法对此进行测试。我确实知道 Bash 3.0+ 和 Zsh 5.5.1 都支持 typeset -p 和 declare -p,不同之处仅在于哪个可以替代另一个。但是我没有测试过这两个关键字之外的差异,也没有测试过其他的shell。

如果您需要脚本与 POSIX sh 兼容,则不能使用数组。没有数组,[ -n “{$var+x}” ] 有效。

Bash中不同方法的比较代码

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

我跳过 test -v var、[ -v var ] 和 [[ -v var ]],因为它们产生与 POSIX 标准 [ -n “${var+x}” ] 相同的结果,同时需要 Bash 4.2+。我也跳过了 typeset -p,因为它与我测试过的 shell(Bash 3.0 到 5.0 和 Zsh 5.5.1)中的 declare -p 相同。

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\n' "$1" $nonempty $plus $count $declared
}

测试用例代码

请注意,如果未将变量声明为关联数组,则由于 Bash 将非数字数组索引视为“0”,因此测试结果可能会出乎意料。此外,关联数组仅在 Bash 4.0+ 中有效。

# Header.
printf '%30s: %2s %2s %2s %2s\n' "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 “ v a r " ] 、 [ − n " var" ]、[ -n " var"][n"{var+x}” ]、[ “${#var[@]}” != 0 ]和declare -p var。

                         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 至少从 3.0 开始,对于在 Bash 中测试命名变量是(100%?)可靠的。 [ -n “${var+x}” ] 在符合 POSIX 的情况下是可靠的,但不能处理数组。存在其他测试来检查变量是否为非空,以及检查其他 shell 中声明的变量。但是这些测试既不适合 Bash 也不适合 POSIX 脚本。

在我尝试过的答案中,这个(declare -p var &>/dev/null)是唯一有效的答案。谢谢你!

此外,使用不带 $ 前缀的变量名称也可以:declare -p PATH &> /dev/null 返回 0,而 declare -p ASDFASDGFASKDF &> /dev/null 返回 1。(在 bash 5.0.11(1)-release 上)

做得好! 1 个注意事项:declare var 将 var 声明为一个变量,但它确实不根据 set -o nounset 设置它:使用 declare foo bar=; set -o nounset; echo $bar; echo $foo 进行测试

@joehanna 感谢您发现丢失的 /!我解决了这个问题,但我认为逻辑混乱到足以保证一个功能,特别是考虑到@xebeche 的评论。 @xebeche 这对我的回答很不方便......看起来我必须尝试像 declare -p "$1" | grep = 或 test -v "$1" 这样的东西。

@xebeche 经过更多测试,似乎 set -o nounset; (echo "$var") &>/dev/null 与 [ -n "${var+x}" ] 具有相同的真值,因此唯一的区别是 set -o nounset 导致脚本/子shell退出。也就是说,我同意我的回答 应该 解释变量被 set 与仅 declared 之间的区别,而不是将这些情况混为一谈。随意编辑。在下一次常年通知之前,我不会回到这个答案。

答9:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

在现代版本的 Bash 上(我认为是 4.2 或更高版本;我不确定),我会试试这个:

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

另请注意,[ -v "$VARNAME" ] 并非不正确,只是执行了不同的测试。假设VARNAME=foo;然后它检查是否设置了一个名为 foo 的变量。

请注意,对于那些想要可移植性的人,-v 不符合 POSIX

如果获得 [: -v: unexpected operator,则必须确保使用 bash 而不是 sh。

答10:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

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

虽然对于参数,我认为通常最好测试 $#,它是参数的数量。

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

第一个测试是落后的;我认为您想要 [ "$1" != "" ](或 [ -n "$1" ])...

如果 $1 设置为空字符串,这将失败。

答案的第二部分(计数参数)是当 $1 设置为空字符串时答案的第一部分不起作用的有用解决方法。

如果 set -o nounset 打开,这将失败。

答11:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

概括

使用 test -n “ v a r − " 检查变量是否不为空(因此也必须定义 / 设置)。用法: i f t e s t − n " {var-}" 检查变量是否不为空(因此也必须定义/设置)。用法: if test -n " var"检查变量是否不为空(因此也必须定义/设置)。用法:iftestn"{var-}”;然后 echo “var is set to <$var>” else echo “var is not set or empty” fi

使用 test -n “ v a r + x " 检查变量是否已定义 / 设置(即使它是空的)。用法: i f t e s t − n " {var+x}" 检查变量是否已定义/设置(即使它是空的)。用法: if test -n " var+x"检查变量是否已定义/设置(即使它是空的)。用法:iftestn"{var+x}”;然后 echo “var is set to <$var>” else echo “var is not set” fi

请注意,第一个用例在 shell 脚本中更为常见,这是您通常想要使用的。

笔记

此解决方案应适用于所有 POSIX shell(sh、bash、zsh、ksh、dash)

这个问题的其他一些答案是正确的,但可能会让没有 shell 脚本经验的人感到困惑,所以我想提供一个 TLDR 答案,让这些人不会感到困惑。

解释

要了解此解决方案的工作原理,您需要了解 POSIX test command 和 POSIX shell 参数扩展 (spec),因此让我们介绍理解答案所需的绝对基础知识。

test 命令对表达式求值并返回真或假(通过其退出状态)。如果操作数是非空字符串,则运算符 -n 返回 true。例如,test -n “a” 返回 true,而 test -n “” 返回 false。现在,要检查一个变量是否不为空(这意味着它必须被定义),您可以使用 test -n “$var”。但是,某些 shell 脚本有一个选项集 (set -u),它会导致对未定义变量的任何引用发出错误,因此如果变量 var 未定义,则表达式 $var 将导致错误。要正确处理这种情况,您必须使用变量扩展,这将告诉 shell 如果未定义变量,则将其替换为替代字符串,从而避免上述错误。

变量扩展 ${var-} 表示:如果变量 var 未定义(也称为“未设置”),则将其替换为空字符串。因此,如果 v a r 不为空, t e s t − n " var 不为空,test -n " var不为空,testn"{var-}" 将返回 true,这几乎总是您想要在 shell 脚本中检查的内容。如果 v a r 未定义或不为空,则反向检查将为 t e s t − z " var 未定义或不为空,则反向检查将为 test -z " var未定义或不为空,则反向检查将为testz"{var-}"。

现在到第二个用例:检查变量 var 是否已定义,是否为空。这是一个不太常见的用例,而且稍微复杂一些,我建议您阅读 Lionels’s great answer 以更好地理解它。

看起来您在对 test -z 的解释中不小心添加了“非”。来自测试的手册页:-z STRING 如果 STRING 的长度为零,则返回 true。因此,如果 var 未定义或为空,test -z "${var-}" 将返回 true。

原文链接:https://www.huntsbot.com/qa/070d/how-to-check-if-a-variable-is-set-in-bash?lang=zh_CN&from=csdn

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值