2

出于某种原因,我无法使用感叹号语法访问数组键:

declare -a sites
sites=(["fr"]="frederick" ["an"]="annapolis")

for i in "${!sites[@]}"
  do
    echo "key: $i "
  done

这只是回显“key:0”

我在这里做错了什么?

另外,我想添加价值。

所以我们的看跌期权是:

键:fr,值:弗雷德里克

4

3 回答 3

0

可以在旧的 bash 版本中完成。

在旧版本的 bash 中,您可以使用整个环境变量集来实现关联数组(也称为哈希)

export HASH_PREFIX="I_AM_A_HASH"

hash-set() {
    HASH_NAME="$1" ; shift
    HASH_KEY="$1"  ; shift
    HASH_VAL="$1"  ; shift
    eval "export ${HASH_PREFIX}_${HASH_NAME}_KEY_${HASH_KEY}='$HASH_VAL'"
}
hash-get() {
    HASH_NAME="$1" ; shift
    HASH_KEY="$1"  ; shift
    eval "echo \"\$${HASH_PREFIX}_${HASH_NAME}_KEY_${HASH_KEY}\""
}
hash-keys() {
    HASH_NAME="$1" ; shift
    HASH_PREFIX_NAME_LENGTH=$(( ${#HASH_PREFIX} + ${#HASH_NAME} + 6 ))
    declare -x | while read -r LINE_READ ; do
        LINE_READ="${LINE_READ:11}"
        if [   x"${LINE_READ:0:HASH_PREFIX_NAME_LENGTH}" \
             = x"${HASH_PREFIX}_${HASH_NAME}_KEY_" \
           ]
        then
            LINE_READ="${LINE_READ:HASH_PREFIX_NAME_LENGTH}"
            LINE_READ="${LINE_READ/=*/}"
           echo "${LINE_READ}"
        fi
    done
}

hash-set sites "fr" "frederick"
hash-set sites "an" "annapolis"

for i in $(hash-keys sites) ; do
    echo "key: $i, value: $(hash-get sites $i)"
done

键被限制为与环境变量相同的字符(0-9、az、AZ、_)。

您可以使用“_xx”来表示非字母数字 ascii 值(例如“_5f”表示“_”,“_3f”表示“?”)。Rosettacode 有如何在纯 bash 中在 ascii 字符和十六进制之间来回转换。

同样在 mac 笔记本电脑上,您可以安装自制软件,然后使用它来安装更新的 bash。您还可以在 awk 或 perl 或 ruby​​ 或 python 中使用完整的关联数组。

于 2019-05-03T20:34:18.620 回答
-1

问题是declare -a

根据手册页,它应该是declare -A.

declare [-aAfFgilrtux] [-p] [name[=value] ...]
    ...
    -a     Each name is an indexed array variable (see Arrays above).
    -A     Each name is an associative array variable (see Arrays above).

试试这个:

declare -A sites
sites=(["fr"]="frederick" ["an"]="annapolis")

for i in "${!sites[@]}"
  do
    echo "key: $i, value: ${sites[$i]}"
  done
于 2012-04-11T16:05:59.027 回答
-1

我认为这可能是缺乏大写的阻碍......

declare -A _sites=( ["fr"]="frederick" ["an"]="annapolis" )

for i in "${!_sites[@]}"; do
    printf '%s -> %s\n' "${i}" "${_sites[$i]}"
done

有助于整理上述内容的资源不限于以下内容;

  • @anubhava关于declare -A使用的回答

  • @lhunath的答案还涵盖了 Bash 版本3或更低版本的解决方法。

在阅读了其他发布的答案的评论后,我认为如果卡在由于某些原因无法更新的旧版 Bash 中,您会想要最后列出的答案的解决方法。


@Fenn还有一些注意事项...

hash-set() {
    HASH_NAME="$1" ; shift
    HASH_KEY="$1"  ; shift
    HASH_VAL="$1"  ; shift
    eval "export ${HASH_PREFIX}_${HASH_NAME}_KEY_${HASH_KEY}='$HASH_VAL'"
}

...没有shifting, or eval, 并且带有必需的参数可能看起来像...

hash_set(){
    local _name="${1:?${FUNCNAME[0]} not provided a Hash Name}"
    local _key="${2:?${FUNCNAME[0]} not provided a Hash Key}"
    local _value="${3:?${FUNCNAME[0]} not provided a Value}"
    declare -g "${HASH_PREFIX}_${_name}_KEY_${_key}='${_value}'"
}

...希望这对于将答案转化为可以投票的东西更有帮助。

于 2019-05-05T18:56:21.337 回答