检查给定变量是否已设置的Bash函数

4

此答案中所解释的那样,在bash中检查变量是否设置的“正确”方法如下:

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

我感兴趣的是如何将这个内容提取成一个函数,以便可以重复使用于不同的变量。
目前为止我最好的做法是:
is_set() {
  local test_start='[ ! -z ${'
  local test_end='+x} ]'
  local tester=$test_start$1$test_end

  eval $tester
}

看起来它能工作,但有没有更好的方法可以避免使用 eval 呢?


创建一个函数来测试变量是否设置好似乎不是一个好主意。你要么硬编码要检查的变量(这没有任何意义),要么使用eval(不推荐),特别是当你不能绝对保证变量内容时,或者将要检查的变量值作为参数传递,这会让你回到最初的[[ -z $1 ]]测试。 - David C. Rankin
5
这里有一个微妙的区别:[[ -z $var ]] 如果 var 是空字符串或未设定,就会返回真。而 [[ -z ${var+x} ]] 则严格测试是否未设置。 - John1024
1
@John1024:好发现! - Cyrus
@DavidC.Rankin 我想写一个函数,让代码自我记录,因为语法相当晦涩。但由于很多复杂性,我同意你的观点,并且这让我思考了一下文档领域逻辑和语言工作方式之间的区别。既然这种语言在这里阻止了我的努力,我将坚持最简单的方式,并不试图将它封装在一个函数中。 - ivan
我不能百分之百确定在bash 3中你会得到相同的结果,但是你可以使用!运算符间接检查一个变量。 isunset() { [[ -z ${!1+x} ]];} 然后你可以使用if isunset var; then echo var is not set - Dave
3个回答

6
在Bash中,您可以使用[[ -v var ]]。不需要函数或复杂的方案。
从man页中得知:
   -v varname
          True if the shell variable varname is set (has been assigned a value).
第一和第二条命令序列打印ok:
[[ -v PATH ]] && echo ok

var="" ; [[ -v var ]] && echo ok

unset var ; [[ -v var ]] && echo ok

我猜这是在比我运行的Bash版本更新的版本中添加的?我得到了bash: conditional binary operator expected,但我正在使用随OSX(3.2.57)一起提供的Bash版本。我应该升级,但我正在编写这个脚本来帮助同事设置他们的开发环境的一部分,所以可移植性是一个问题。 - ivan
1
然后像之前指出的那样,一种更加简洁的方法是 [[ -z ${var+x} ]]。它在 Bash 3 中可以工作吗?在函数中运行 eval 进行简单检查是丑陋而且容易出问题的做法。 - Ricardo Branco
1
是的,在 Bash 3 中 [[ -z ${var+x} ]] 这种方法可以工作。我会坚持使用它。不过知道 -v 也被添加进来了还是很棒的,谢谢! - ivan

2

使用[[ ... ]],您可以简单地执行此操作(无需使用双引号):

[[ $var ]] && echo "var is set"
[[ $var ]] || echo "var is not set or it holds an empty string"

如果你真的需要一个函数,我们可以编写一行代码:

is_empty()     { ! [[ $1 ]]; } # check if not set or set to empty string
is_not_empty() {   [[ $1 ]]; } # check if set to a non-empty string

var="apple"; is_not_empty "$var" && echo "var is not empty" # shows "var is not empty"
var=""     ; is_empty "$var"     && echo "var is empty"     # shows "var is empty"
unset var  ; is_empty "$var"     && echo "var is empty"     # shows "var is empty"
var="apple"; is_empty "$var"     || echo "var is not empty" # shows "var is not empty"

最后,可以实现is_unsetis_set来将$1作为变量名处理:

is_unset() {   [[ -z "${!1+x}" ]]; }           # use indirection to inspect variable passed through $1 is unset
is_set()   { ! [[ -z "${!1+x}" ]]; }           # check if set, even to an empty string

unset var; is_unset var && echo "var is unset" # shows "var is unset"
var=""   ; is_set var   && echo "var is set"   # shows "var is set"
var="OK" ; is_set var   && echo "var is set"   # shows "var is set"

相关


0

Bash 4.2+

if [[ -v $MY_VARIABLE ]]; then
    echo "MY_VARIABLE is set"
fi

旧版本(MacOS)

if [[ -n ${MY_VARIABLE+set} ]]; then
    echo "MY_VARIABLE is set"
else

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接