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

如何无eval反序列化${aa[@]@K}到关联数组并重赋值

Bash中关联数组的引用与${parameter@K}序列化字符串的反序列化(避免eval的尝试)

问题说明

需要实现:通过${parameter@K}生成的序列化字符串(来自外部,比如文件读取,实际场景中无原数组变量),将内容赋值给通过declare -n引用的关联数组,目标是避免使用eval。

${parameter@K} 生成参数值的带引号版本,对关联数组会输出带引号的键值对序列。

初始测试代码

#!/bin/bash

func() {
        declare -n aa=$1
        # `aa=()`可用于清空引用数组后填充,此处省略以观察引用丢失情况

        # 实际代码中仅serialized字符串可用
        declare -A aa_original=("a" "3" "b" "4") 
        serialized=$(printf '%s' "${aa_original[@]@K}")

        aa="( $serialized )"

        # 以下仅用于调试
        echo "~ at the end of func() now"
        echo "~ serialized: $serialized"
        echo "~ aa_original:"
        for key in "${!aa_original[@]}"; do printf "%s->%s " $key ${aa_original[$key]}; done
        echo
        echo "~ aa:"
        for key in "${!aa[@]}"; do printf "%s->%s " $key ${aa[$key]}; done
        echo
        echo "~ leaving func() now"
}

declare -A AA=("a" "1" "b" "2")

func AA

echo "${AA["a"]} ~ ${AA["b"]}"

预期最终输出3 ~ 4,实际输出1 ~ 2,全局数组AA被破坏,调试输出如下:

~ at the end of func() now
~ serialized: b "4" a "3" 
~ aa_original:
b->4 a->3 
~ aa:
0->( b->"4" a->"3" )-> b->2 a->1 
~ leaving func() now

尝试显式声明declare -A的问题

修改赋值语句为:

declare -A aa="( $serialized )"

赋值成功,但丢失了declare -n的引用属性,调试输出如下:

~ at the end of func() now
~ serialized: b "4" a "3" 
~ aa_original:
b->4 a->3 
~ aa:
b->4 a->3 
~ leaving func() now
1 ~ 2

可行解决方案

方案1:临时本地数组中转

通过创建临时本地数组接收序列化内容,再遍历填充到引用数组中:

#!/bin/bash

func() {
        declare -n aa=$1

        serialized=$(declare -A aa_original=("a" "3" "b" "4"); printf '%s' "${aa_original[@]@K}")

        # 创建临时本地数组
        declare -A aa_local="( $serialized )"

        # 清空并重新填充引用数组
        aa=()
        for key in "${!aa_local[@]}"; do aa["$key"]="${aa_local[$key]}"; done
}

declare -A AA=("a" "1" "b" "2")

func AA

echo "${AA["a"]} ~ ${AA["b"]}"

方案2:简化的eval方案

经提示,上述中转方案与直接使用eval等效,以下是更简洁的实现,支持${parameter@K}输出的$'...'ANSI-C引号结构:

#!/bin/bash

func() {
        declare -n aa=$1

        serialized=$(declare -A aa_original=("a" "3" "b" "4"); printf '%s' "${aa_original[@]@K}")

        aa=()
        eval aa="( $serialized )"
}

declare -A AA=("a" "1" "b" "2")

func AA

echo "${AA["a"]} ~ ${AA["b"]}"

目前针对${parameter@K}的输出,无eval的实现无法完成需求,上述方案是当前最优解。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 23:30:00