使用 unset 与将变量设置为空

我目前正在编写一个 bash 测试框架,其中在测试函数中可以使用标准 bash 测试([[)和预定义的匹配器。匹配器是’[[’的包装器,除了返回一个返回代码之外,还设置一些有意义的消息,说明预期的结果。

例如:

string_equals() {
if [[ ! $1 = $2 ]]; then
error_message="Expected '$1' to be '$2'."


return 1
fi
}

So, when a matcher is used, and it fails, only then an error_message is set.

现在,稍后,我将测试这些测试是否成功。如果成功了,我用绿色打印期望,如果失败了,用红色打印。

Furthermore, there may be an error_message set, so I test if a message exists, print it, and then unset it (because the following test may not set an error_message):

if [[ $error_message ]]; then
printf '%s\n' "$error_message"


unset -v error_message
fi

现在我的问题是,取消变量设置是更好,还是直接设置为“ ,比如

error_message=''

哪个更好?有什么区别吗?或者也许我应该有一个额外的标志,表明消息已设置?

212209 次浏览

大多数情况下,你看不出有什么不同,除非你使用 set -u:

/home/user1> var=""
/home/user1> echo $var


/home/user1> set -u
/home/user1> echo $var


/home/user1> unset var
/home/user1> echo $var
-bash: var: unbound variable

实际上,这取决于你如何测试这个变量。

我还要补充一点,如果设置好了,我首选的测试方法是:

[[ -n $var ]]  # True if the length of $var is non-zero

或者

[[ -z $var ]]  # True if zero length

如前所述,对数组使用 unset 也是不同的

$ foo=(4 5 6)


$ foo[2]=


$ echo ${#foo[*]}
3


$ unset foo[2]


$ echo ${#foo[*]}
2

So, by unset'ting the array index 2, you essentially remove that element in the array and decrement the array size (?).

我自己做了个测试。

foo=(5 6 8)
echo ${#foo[*]}
unset foo
echo ${#foo[*]}

结果是. 。

3
0

So just to clarify that unset'ting the entire array will in fact remove it entirely.

基于上面的评论,这里有一个简单的测试:

isunset() { [[ "${!1}" != 'x' ]] && [[ "${!1-x}" == 'x' ]] && echo 1; }
isset()   { [ -z "$(isunset "$1")" ] && echo 1; }

例如:

$ unset foo; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's unset
$ foo=     ; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's set
$ foo=bar  ; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's set