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
相关产品推荐
相关产品推荐

