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

Bash循环中加入数组的关联数组均指向最后值 如何定义唯一变量实例

问题根因

  • Bash 原生不支持将关联数组直接作为元素存入普通数组,原代码中periods+=(period)实际仅存储了字符串period,而非关联数组的内容。
  • 循环中未指定作用域的declare -A period会复用同一个全局关联数组变量,每次赋值都会覆盖之前的内容,导致所有引用最终都指向最后一次的赋值结果。
  • 末尾遍历的写法存在错误,"${!periods[@]}"获取的是periods数组的下标列表,而非存储的元素值。

解法1:使用nameref(变量引用,需Bash 4.3及以上版本)

最贴近你原本的实现思路,通过动态生成唯一的关联数组名,结合nameref实现赋值和取值:

#!/usr/bin/env bash

periods=()
# 用于生成唯一变量名的计数器
idx=0

for arg
do
    echo "arg: $arg"

    day= month= year=

    case $arg in
      */*/* | *-*-*)
          read -r year month day < <(date '+%Y %m %d' -d "$arg")
          ;;
      ????[-/]?? | ????[-/]?)
          IFS='-/' read -r year month <<< "$arg"
          ;;
      ??[-/]???? | ?[-/]????)
          IFS='-/' read -r month year <<< "$arg"
          ;;
    esac

    # 生成唯一的关联数组变量名
    local varname="period_$idx"
    # 声明关联数组
    declare -A "$varname"
    # 用nameref指向这个动态变量,方便赋值
    declare -n period="$varname"

    period[year]=$year 
    period[month]=$month 
    period[day]=$day

    # 把变量名存到数组里
    periods+=("$varname")
    # 计数器自增
    ((idx++))
    # 解除nameref绑定
    unset -n period
done

# 遍历展示
for varname in "${periods[@]}"
do
    # 重新绑定nameref
    declare -n period="$varname"
    echo "year: ${period[year]} / month: ${period[month]} / day: ${period[day]}"
    unset -n period
done

解法2:序列化存储(兼容低版本Bash)

如果运行环境的Bash版本较低,可以将每个关联数组的键值对序列化为固定格式的字符串存入数组,取值时再反序列化为关联数组:

#!/usr/bin/env bash

periods=()

for arg
do
    echo "arg: $arg"

    day= month= year=

    case $arg in
      */*/* | *-*-*)
          read -r year month day < <(date '+%Y %m %d' -d "$arg")
          ;;
      ????[-/]?? | ????[-/]?)
          IFS='-/' read -r year month <<< "$arg"
          ;;
      ??[-/]???? | ?[-/]????)
          IFS='-/' read -r month year <<< "$arg"
          ;;
    esac

    # 序列化格式:year=xxx,month=xxx,day=xxx
    periods+=("year=$year,month=$month,day=$day")
done

# 遍历展示
for entry in "${periods[@]}"
do
    declare -A period
    # 拆分字符串赋值
    IFS=',' read -r -a kv_pairs <<< "$entry"
    for kv in "${kv_pairs[@]}"
    do
        IFS='=' read -r key val <<< "$kv"
        period["$key"]="$val"
    done
    echo "year: ${period[year]} / month: ${period[month]} / day: ${period[day]}"
done

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 13:06:06