代码之家  ›  专栏  ›  技术社区  ›  Hielke Walinga

我可以循环使用与bash和zsh语法相同的关联数组的键吗

  •  0
  • Hielke Walinga  · 技术社区  · 6 年前

    我想循环一个关联数组的键,但是我想让我的脚本在zsh和bash中工作。有没有一种方法(语法)可以同时使用

    我知道这个

    ZSH:

    for k in "${(k)array[@]}" do echo $k; done
    

    猛击:

    for k in "${!array[@]}" do echo $k; done
    

    顺便说一下,我实际上使用的是我的zsh,所以我不能真正使用 emulate ksh 因为它让我的终端崩溃。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Charles Duffy    6 年前

    您可以将每个实现包装在一个函数中,并且只定义适合当前shell的函数:

    if [[ $ZSH_VERSION ]]; then
      keys_for_array() {
        local array=$1 dest=$2
        [[ $1 && $2 ]] || { echo "Usage: keys_for_array source-array dest-array" >&2; return 1; }
        : ${(AP)dest::=${(kP)array}}
      }
    elif [[ $BASH_VERSION && ! $BASH_VERSION =~ ^([123][.]|4[.][012]) ]]; then
      keys_for_array() {
        [[ $1 && $2 ]] || { echo "Usage: keys_for_array source-array dest-array" >&2; return 1; }
        local -n array=$1 dest=$2
        eval 'dest=( "${!array[@]}" )'
      }
    else
      keys_for_array() { echo "ERROR: keys_for_array not available for this shell" >&2; return 1; }
    fi
    
    [[ $ZSH_VERSION ]] && typeset -A aa=( 1 one 2 two )
    [[ $BASH_VERSION ]] && declare -A aa=( [1]=one [2]=two )
    keys_for_array aa aak
    
    declare -p aak
    

    …在bash上运行时,输出为:

    declare -a aak=([0]="1" [1]="2")
    

    …在zsh上运行时,输出为:

    typeset -a aak=( 1 2 )
    

    在任何一种情况下,您都可以对它们进行迭代:

    keys_for_array aa aak
    for key in "${aak[@]}"; do
      echo "Key $key has value ${aa[$key]}"
    done
    

    注意,上面的两个函数在两个shell中在语法上都是有效的。否则,可能需要使用 eval source 只在有条件的情况下把它们拉进去。就我个人而言,我将使用可移植性库的bash和zsh版本创建两个单独的文件,并且只从源代码中获取适合当前shell的文件。