在bash中取消设置变量检查

Posted

技术标签:

【中文标题】在bash中取消设置变量检查【英文标题】:unset variable check in bash 【发布时间】:2014-09-03 21:26:45 【问题描述】:

我声明了两个变量但未设置:

__var1=
__var2=

现在我将__var2 设置为具有一些价值:

__var2=1

当我尝试进行这样的检查时:

[ -z "$__var1" -a -z "$__var2" ] || echo "Both missing!"

我收到了这条消息Both missing!。但这是不正确

这是为什么呢?以及如何进行适当的检查,看看它们是否都丢失了?

【问题讨论】:

bash 4.2 开始,您可以使用-v 来测试是否设置了变量,而-z 将在变量未设置或设置为空字符串时为真: -v __var1(不是没有美元符号;-v 采用变量的名称,而不是变量扩展为的字符串)。 很高兴知道,但是在我的脚本中,我确实声明了我的变量,只是想知道它们是__var1= 还是__var1=something 只是声明它们就被认为是设置,这不是很奇怪吗? 你没有在 shell 中声明变量。为未设置的名称分配一个值(var=var="" 是等效的;两者都将空字符串分配给var)使其成为一个设置变量。换句话说,shell 中不存在没有值的变量。 foo=; [[ -v foo ]] && echo "foo is set"; [[ ! -v bar ]] && echo "bar is not set". 【参考方案1】:

如果用户想检查变量是否真的没有设置,而不仅仅是一个空值,你可以这样做:

$ A=1234
$ [[ -z $A+. ]] && echo "Variable is unset."
$ A=
$ [[ -z $A+. ]] && echo "Variable is unset."
$ unset A
$ [[ -z $A+. ]] && echo "Variable is unset."
Variable is unset.

在你的情况下可能是

[[ -z $__var1+. && -z $__var2+. ]] && echo "Both variables are unset!"

【讨论】:

var 是一个集合变量时,$var+something 格式扩展为something,否则没有。你可以试试echo 所以即使你做variable=也被认为是设置?【参考方案2】:

@Dave Schweissguth's answer 很好地说明了您的代码的逻辑,但对于语法也有一些需要注意的地方:

[更新:问题的原始形式使用了诸如 $__var1= 之类的赋值 - 这已被更正] 在 Bourne-like/POSIX-compatible shells 中,您不要赋值一个值时使用$前缀,只有在引用它时;因此,你的作业应该是:
__var1=
__var2= # or, later: __var2=1
您的问题被标记为bash,因此最好的 bash 方式来编写您的可能是:
[[ -z $__var1 && -z $__var2 ]] && echo "Both missing!"

注意[[ ... ]] rater 的使用比[ ... ] 的使用,这避免了将操作数双引号到-z 的需要。

相比之下,最便携(符合 POSIX)的方式是:
[ -z "$__var1" ] && [ -z "$__var2" ] && echo "Both missing!"

【讨论】:

所以在[[ 中,未设置的变量会自动替换为某些东西,这样-z 一元运算符就不会丢失它的操作数? @branquito:是的,这是使用[[ ... ]] 的优势之一。 我想在那种情况下它会变成"" @branquito:粗略地说,是的。更准确地说,[[ ... ]] 条件句的解析不同于 [ ... ] 及其等价物test:后者的解析方式类似于命令行,而[[ ... ]] 的解析方式更像传统编程语言:而不是扩展$__var1 首先,然后评估结果(与[ ... ] / test一样),表达式被解析一次性,所以bash 知道那里有 一个操作数,即使未定义或为空。 (这有点投机,但我希望它足够接近真相——并且依靠它在实践中有效。) 有点意外,但-a 不符合 POSIX 标准吗? [[ ]] btw 说得好。【参考方案3】:

您的代码显示“两个都不见了!”如果两个 (-a) 变量都为空 (-z) 不是真的 (||)。如果这是真的,您想打印该消息。这样做:

[ -z "$__var1" -a -z "$__var2" ] && echo "Both missing!"

我不记得曾经见过没有 -z-a 的 bash 或 test 版本(sh 使用什么来评估相同的表达式),所以据我所知,上述内容适用于任何类 Unix您可能会找到的系统。

【讨论】:

我一定是太累了,错过了这些东西:) Re -a-o:POSIX 确实 允许 使用它们,但发出以下 警告 (man.cx/test) - 强调我的:“在处理用户提供的输入时,脚本应该小心,因为这些输入可能会与主元素和运算符混淆。除非应用程序编写者知道所有产生脚本输入的情况,否则像:test "$1" -a "$2" 这样的调用应该写成:@987654331 @ 以避免在用户提供的值(例如 $1 设置为 '!' 和 $2 设置为空字符串时出现问题。[...] 考虑最大可移植性的地方 [...] [使用] test expr1 && test expr2 "

以上是关于在bash中取消设置变量检查的主要内容,如果未能解决你的问题,请参考以下文章

使用非标准名称取消设置 bash 函数变量

Bash条件表达式(-v)检查是不是设置了变量[重复]

如何检查变量是不是未设置并在我的 bash 前奏中使用 set -u? [复制]

取消设置单个命令的环境变量

如何取消设置鱼壳中的变量?

Bash 取消声明只读变量(声明 -r var)