【问题标题】:How can I check if an associative array element exists in my Bash script?如何检查我的 Bash 脚本中是否存在关联数组元素?
【发布时间】:2015-08-25 07:07:35
【问题描述】:

我有一系列动物:

declare -A animals=()
animals+=([horse])

我想检查动物是否存在:

if [ -z "$animals[horse]"]; then
    echo "horse exists";
fi

但这不起作用。

【问题讨论】:

标签: bash


【解决方案1】:

有点老了,但在我搜索答案的时候出现了,我的系统没有bash 4.3,我特别关心animals[horse-2]示例

另一种方法是将内容转储出数组,然后检查子字符串是否匹配 -

declare -A animals
animals[horse-2]=neigh-2
animals[dog]=woof
animals_as_string=$(declare -p animals)
other_animals="horse-2 moose cow"

for animal in $other_animals
do
  if [[ "$animal" == *$animals_as_string" ]]; then
    echo "found $animal"
  fi
done

当然,在搜索 animals[horse] 时,您需要更多的东西来确保没有找到动物[horse-2](如果您的数组中有它)

【讨论】:

    【解决方案2】:

    bash 4.3 中,-v 运算符可以应用于数组。

    declare -A animals
    animals[horse]=neigh
    # Fish are silent
    animals[fish]=
    [[ -v animals[horse] ]] && echo "horse exists"
    [[ -v animals[fish] ]] && echo "fish exists"
    [[ -v animals[unicorn] ]] || echo "unicorn does not exist" 
    

    在以前的版本中,您需要更加小心地区分不存在的键和引用任何空字符串的键。

    animal_exists () {
        # If the given key maps to a non-empty string (-n), the
        # key obviously exists. Otherwise, we need to check if
        # the special expansion produces an empty string or an
        # arbitrary non-empty string.
        [[ -n ${animals[$1]} || -z ${animals[$1]-foo} ]]
    }
    
    animal_exists horse && echo "horse exists"
    animal_exists fish && echo "fish exists"
    animal_exists unicorn || echo "unicorn does not exist"
    

    【讨论】:

    • 上述答案第一部分的错字。最后一行应该是:[[ -v animals[unicorn] ]] || echo "unicorn does not exist" 而不是[[ -v animals[unicorn] ]] && echo "unicorn does not exist" 此外,测试命令不需要是双括号。单括号也可以。
    • 我更喜欢使用双括号,因为-v 不是[ 的POSIX 标准的一部分,如果你有-v,你也有[[。跨度>
    【解决方案3】:

    您的脚本中有几个拼写错误

    当我按原样运行它时,我从 BASH 收到以下错误消息:

    1. animals: [horse]: must use subscript when assigning associative array
    2. [: missing `]'
    

    第一个说如果你想使用horse 作为关联数组的索引,你必须给它赋值。空值(null)是可以的。

    -animals+=([horse])
    +animals+=([horse]=)
    

    第二条消息说您需要将要测试的值和括号分开,因为方括号如果不被空格分隔,则被认为是值的一部分

    -if [ -z "$animals[horse]"]; then
    +if [ -z "$animals[horse]" ]; then
    

    最后,关联数组中的元素在有赋值时存在(即使该值为空)。由于测试是否设置了数组值的问题已经answered on this site,我们可以借用解决方案

    -if [ -z "$animals[horse]"]; then
    +if [ -n "${animals[horse]+1}" ]; then
    

    为了您的方便,这里是完整的脚本:

    declare -A animals=()
    animals+=([horse]=)
    
    if [ -n "${animals[horse] + 1}" ]; then
        echo "horse exists";
    fi
    

    【讨论】:

    • animals[horse]=比使用+=简单得多
    • @chepner 很公平,除非 OP 想要一次定义多个元素。
    【解决方案4】:

    在 BASH 中你可以这样做:

    declare -A animals=()
    animals+=([horse]=)
    
    [[ "${animals[horse]+foobar}" ]] && echo "horse exists"
    

    "${animals[horse]+foobar}" 如果horse 是数组中的有效索引,则返回foobar,否则不返回任何内容。

    【讨论】:

    • 对不起,... "animals+=([horse]=)" 行末尾的= 是什么意思
    • 即为索引horse分配一个空值。 animals+=([horse]) 否则会给出语法错误。
    猜你喜欢
    • 2018-02-24
    • 2020-04-11
    • 2012-12-31
    • 1970-01-01
    • 2010-12-30
    • 2015-07-31
    • 1970-01-01
    相关资源
    最近更新 更多