【问题标题】:Bash check if array of variables have values or notBash 检查变量数组是否有值
【发布时间】:2020-02-28 09:29:12
【问题描述】:

我有一个变量数组。我想使用 for 循环检查变量是否有值。

我将值放入循环中,但 if 条件失败

function check {
    arr=("$@")
    for var in "${arr[@]}"; do
        if [ -z $var ] ; then
            echo $var "is not available"
        else
            echo $var "is available"
        fi
    done
}

name="abc"
city="xyz"
arr=(name city state country)
check ${arr[@]}

对于以上内容,我得到了所有可用

预期输出是

name is available
city is available
state is not available
country is not available

【问题讨论】:

  • var 在您的循环中采用值 namecitystatecountry。 [ -z ... ] 测试参数的长度是否为零。这些单词的长度都不为零,因此每次都采用else 分支。

标签: bash shell


【解决方案1】:

这是您任务的正确语法

if [ -z "${!var}" ] ; then
    echo $var "is not available"
else
    echo $var "is available"
fi

说明,此方法使用间接变量扩展,此构造${!var} 将扩展为名称在$var 中的变量的值。

稍微改变了check函数

check () {
    for var in "$@"; do
        [[ "${!var}" ]] && not= || not="not "
        echo "$var is ${not}available"
    done
}

还有一个使用declare的变体

check () {
    for var in "$@"; do
        declare -p $var &> /dev/null && not= || not="not "
        echo "$var is ${not}available"
    done
}

来自declare帮助

$ declare --help
declare: declare [-aAfFgilnrtux] [-p] [name[=value] ...]
    Set variable values and attributes.
    Declare variables and give them attributes.  If no NAMEs are given,
    display the attributes and values of all variables.
    ...
    -p  display the attributes and value of each NAME
    ...

实际上所有的变量都可以用这个一次性检查

check () {
    declare -p $@ 2>&1 | sed 's/.* \(.*\)=.*/\1 is available/;s/.*declare: \(.*\):.*/\1 is not available/'
}

【讨论】:

  • 如果你能解释一下变化就太好了。
  • -z string 如果字符串的长度为零,则为真。
  • 这有一个错误 - 带有空格的值的变量将导致来自test 的错误消息。
  • 如果空格不是有效值,则不是错误,而是功能)
  • 我只是遵循 OPs 风格
【解决方案2】:

虽然间接是一种可能的解决方案,但可以使用not really recommended。更安全的方法是使用关联数组:

function check {
    eval "declare -A arr="${1#*=}
    shift
    for var in "$@"; do
        if [ -z "${arr[$var]}" ] ; then
            echo $var "is not available"
        else
            echo $var "is available"
        fi
    done
}

declare -A list
list[name]="abc"
list[city]="xyz"

check "$(declare -p list)" name city state country

这会返回:

name is available
city is available
state is not available
country is not available

以下问题用于创建此答案: How to rename an associative array in Bash?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 2011-12-19
    • 2011-02-26
    • 1970-01-01
    • 2021-01-13
    • 2021-06-11
    • 2013-10-22
    相关资源
    最近更新 更多