在bash中声明和null(空)的定义不一致?

时间:2017-09-22 09:49:27

标签: bash

简介

我试图测试是否声明了变量,但未分配值。

根据this definition(引用POSIX规范)声明表示指定变量的类型,而设置表示为其赋值。并且null(空字符串)被认为是有效值。

实验

然而仅声明变量也会为其指定一个空字符串:

declare var_a
[ -n "${var_a+set}" ] && echo "var_a is set to \"$var_a\""

将此复制/粘贴到终端中,输出为:var_a is set to ""

声明一个未设置的数组根据上面的定义按预期工作:

declare -a var_b

[ -n "${var_b+set}" ] && echo "var_b is set to \"$var_b\""

这不会给出任何输出。

即使声明具有此语法的数组也无法设置它:

var_c=()
[ -n "${var_c+set}" ] && echo "var_c is set to \"$var_c\""

但是设置一个变量,然后再次取消设置似乎实际上是" undeclare"它:

declare var_d
[[ $(declare | grep ^var_d) ]] && echo "var_d is declared" || echo "var_d is not declared" # --> declared

var_d=some_value
[[ $(declare | grep ^var_d) ]] && echo "var_d is declared" || echo "var_d is not declared" # --> declared

unset var_d
[[ $(declare | grep ^var_d) ]] && echo "var_d is declared" || echo "var_d is not declared" # --> not declared

这里最后一个语句的输出是:var_d is not declared

最后,根据这些实验,我希望声明一个变量local(在函数中),然后取消它,然后再次分配它实际上会使它成为一个全局变量(因为它是"未申报&#34):

function someFunction() {
    local var_e="some local value"
    unset var_e
    declare var_e="some global value"
}

someFunction
[ -n "${var_e+set}" ] && echo "var_e is set to \"$var_e\"" || echo "var_e is not set"

只需验证declarelocal在工作方式上是否相似local manual暗示说明"该选项可以是declare")接受的任何选项:

function anotherFunction() {
    local var_f
    [[ $(declare | grep ^var_f) ]] && echo "var_f is declared" || echo "var_f is not declared" # --> declared

    var_f=some_value
    [[ $(declare | grep ^var_f) ]] && echo "var_f is declared" || echo "var_f is not declared" # --> declared

    unset var_f
    [[ $(declare | grep ^var_f) ]] && echo "var_f is declared" || echo "var_f is not declared" # --> not declared
}

# local can only be used in a function, hence the function call
anotherFunction

这里最后一个语句的输出是:var_f is not declared

问题

我想知道我的理解是否不完整,或者bash在这个领域是否一致;

  1. 数组和标量变量的这种不同行为背后的基本原理是什么(即标量初始化为值,而数组则不是)?
  2. 为什么实际上未设置" undeclare"?
  3. "宣布"的规范定义是什么?和"设置"?
  4. 如何可靠地确定是否声明了任何变量(数组或标量),但未设置?
  5. PS:上面的代码示例可以简单地在终端会话中进行复制/粘贴(如果您愿意,可以在同一个会话中进行复制)

1 个答案:

答案 0 :(得分:2)

我不回答你的所有问题。但是,简单地声明标量变量不会为其赋值:

这将涵盖3个条件:未设置,设置但为空,设置为值

if [[ -n ${foo+unset} ]]; then
    if [[ -n $foo ]]; then
        echo foo is not empty
    else
        echo foo is empty
    fi
else
    echo foo is unset
fi

简单地声明变量不会给它一个值:

$ unset foo
$ if [[ -n ${foo+unset} ]]; then if [[ -n $foo ]]; then echo foo is not empty; else echo foo is empty; fi; else echo foo is unset; fi
foo is unset

$ declare foo
$ if [[ -n ${foo+unset} ]]; then if [[ -n $foo ]]; then echo foo is not empty; else echo foo is empty; fi; else echo foo is unset; fi
foo is unset

$ foo=
$ if [[ -n ${foo+unset} ]]; then if [[ -n $foo ]]; then echo foo is not empty; else echo foo is empty; fi; else echo foo is unset; fi
foo is empty

$ foo=x
$ if [[ -n ${foo+unset} ]]; then if [[ -n $foo ]]; then echo foo is not empty; else echo foo is empty; fi; else echo foo is unset; fi
foo is not empty