You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash函数接收普通/关联数组参数异常及传递键的方法问询

如何将关联数组的键传递给使用nameref的Bash函数?

问题描述

在Apple M1最新系统的zsh终端中,编写了Bash函数run_aws_ssm_delete_parameters,使用nameref(-n)接收数组参数。传递普通索引数组时,函数能正确识别3个值;但传递关联数组的键(${!associative_array[@]})时仅识别2个值;直接传递关联数组名时,函数会传递数组的值而非键。

相关代码及运行输出如下:

原始函数与main逻辑

#!/usr/bin/env bash

function run_aws_ssm_delete_parameters() {
    local -r enable_logging="$1"
    local -n parameter_names="$2"
    shift 2

    local -a aws_cli_flags=(
        "delete-parameters"
        "--names"
        "${parameter_names[@]}"
    )

    aws_cli_flags+=("$@")

    set -x
    if result="$(aws ssm "${aws_cli_flags[@]}")"; then
        set +x
        [[ "${enable_logging}" = true ]] && printf "Good: %s\n" "${result}"
        return 0
    else
        set +x
        printf "Bad: %s" "$?"
        return 1
    fi
}

function main() {
    local -a normal_array=("one" "two" "three")
    run_aws_ssm_delete_parameters true normal_array --color on

    local -A associative_array=(
        ["one"]="value_one"
        ["two"]="value_two"
        ["three"]="value_three"
    )

    run_aws_ssm_delete_parameters true "${!associative_array[@]}" --color on
}

main "$@"

原始运行输出(关注--names参数)

++ aws ssm delete-parameters --names one two three --color on

Unable to locate credentials. You can configure credentials by running "aws configure".
+ result=
+ set +x
Bad: 0++ aws ssm delete-parameters --names three one --color on

Unable to locate credentials. You can configure credentials by running "aws configure".
+ result=
+ set +x
Bad: 0%     

直接传递关联数组名的尝试

修改后的main函数:

function main() {
    local -a normal_array=("one" "two" "three")
    run_aws_ssm_delete_parameters true normal_array --color on

    local -A associative_array=(
        ["one"]="value_one"
        ["two"]="value_two"
        ["three"]="value_three"
    )

    run_aws_ssm_delete_parameters true associative_array --color on
}

main "$@"

对应的运行输出:

++ aws ssm delete-parameters --names one two three --color on

Unable to locate credentials. You can configure credentials by running "aws configure".
+ result=
+ set +x
Bad: 0++ aws ssm delete-parameters --names value_two value_three value_one --color on

Unable to locate credentials. You can configure credentials by running "aws configure".
+ result=
+ set +x
Bad: 0% 

问题分析

  1. 传递${!associative_array[@]}时,Bash会直接展开为关联数组的键列表(顺序不固定),但此时传递给函数的是展开后的字符串列表而非数组引用,函数中的nameref会将其视为普通变量,导致${parameter_names[@]}无法正确识别所有元素。
  2. 直接传递关联数组名时,nameref引用的是关联数组本身,${parameter_names[@]}默认会取关联数组的值而非键,这是Bash关联数组的特性。

解决方案

方法1:将关联数组的键存入普通索引数组后传递

先把关联数组的键提取到普通索引数组中,再将该数组名传递给函数,nameref即可正确识别数组所有元素:

修改后的main函数:

function main() {
    local -a normal_array=("one" "two" "three")
    run_aws_ssm_delete_parameters true normal_array --color on

    local -A associative_array=(
        ["one"]="value_one"
        ["two"]="value_two"
        ["three"]="value_three"
    )
    # 将关联数组的键存入普通索引数组
    local -a assoc_keys=("${!associative_array[@]}")
    # 传递这个索引数组名
    run_aws_ssm_delete_parameters true assoc_keys --color on
}

main "$@"

方法2:修改函数以支持直接处理关联数组的键

让函数自动判断变量类型,关联数组则取键,普通数组则取元素:

修改后的函数:

function run_aws_ssm_delete_parameters() {
    local -r enable_logging="$1"
    local -n parameter_names="$2"
    shift 2

    local -a target_elements
    # 判断变量是否为关联数组
    if [[ "$(declare -p parameter_names 2>/dev/null)" == "declare -A"* ]]; then
        # 关联数组,取键
        target_elements=("${!parameter_names[@]}")
    else
        # 普通数组,取元素
        target_elements=("${parameter_names[@]}")
    fi

    local -a aws_cli_flags=(
        "delete-parameters"
        "--names"
        "${target_elements[@]}"
    )

    aws_cli_flags+=("$@")

    set -x
    if result="$(aws ssm "${aws_cli_flags[@]}")"; then
        set +x
        [[ "${enable_logging}" = true ]] && printf "Good: %s\n" "${result}"
        return 0
    else
        set +x
        printf "Bad: %s" "$?"
        return 1
    fi
}

此时直接传递关联数组名即可:

run_aws_ssm_delete_parameters true associative_array --color on

验证结果

两种方法修改后,运行输出中的--names参数都会正确包含三个键:

++ aws ssm delete-parameters --names one two three --color on

内容的提问来源于stack exchange,提问作者PirateApp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 12:37:27