【问题标题】:values to array from variable names with pattern从具有模式的变量名称到数组的值
【发布时间】:2019-05-03 03:35:19
【问题描述】:

我有未知数量的具有模式 rundate* 的变量名称。例如,rundate=180618 && rundate2=180820。我从here 知道我可以将多个变量名称发送到第三个变量:alld=(`echo "${!rundate*}"`),并且在尝试解决我的问题时,我想出了如何将多个变量索引发送到第三个变量:alld_indices=(`echo "${!alld[@]}"`)。但是,如何将多个值发送到我的第三个变量:alld_values,这样echo ${alld_values[@]} 就会给出180618 180820。我从here 知道如何获得第一个值:firstd_value=(`echo "${!alld}"`)。我怀疑,我已经在搜索中看到了答案,但没有意识到。如果是这样的话,很高兴删除我的问题。谢谢!

【问题讨论】:

  • 谢谢@Paul Hodges 和 Charles Duffy。所有四个答案都很好。非常好的细节和背景!

标签: bash


【解决方案1】:
#!/usr/bin/env bash

# set up some test data
rundate="180618"
rundate1="180820"
rundate2="Values With Spaces Work Too"

# If we know all values are numeric, we can use a regular indexed array
# otherwise, the below would need to be ''declare -A alld=( )''
alld=( )                       # initialize an array
for v in "${!rundate@}"; do    # using @ instead of * avoids IFS-related bugs
  alld[${v#rundate}]=${!v}     # populate the array, using varname w/o prefix as key
done

# print our results
printf 'Full array definition:\n   '
declare -p alld                 # emits code that, if run, will redefine the array
echo; echo "Indexes only:"
printf ' - %s\n' "${!alld[@]}"  # "${!varname[@]}" expands to the list of keys
echo; echo "Values only:"
printf ' - %s\n' "${alld[@]}"   # "${varname[@]}" expands to the list of values

...正确地作为输出发出:

Full array definition:
   declare -a alld=([0]="180618" [1]="180820" [2]="Values With Spaces Work Too")

Indexes only:
 - 0
 - 1
 - 2

Values only:
 - 180618
 - 180820
 - Values With Spaces Work Too

...正如您在https://ideone.com/yjSD1J 看到的那样运行

【讨论】:

  • 关联数组建议可能有问题。我试图用rundate="180618" && rundate1="180820" && declare -A alld=( ) && for v in "${!rundate@}"; do alld[${v#rundate}]=${!v}; done 进行验证,但得到了 -bash: alld[${v#rundate}]: bad array subscript
  • 对,那是因为空字符串不是有效的键。如果您要走关联路线,只需将其设为$v,而不是${v#rundate}。在更改代码以使用索引数组(其中空字符串计算为0)而不是关联数组(其中无效)时,我只放回#rundate 是有原因的。
【解决方案2】:

eval 在循环中会这样做。

$: for v in ${!rundate*}
>  do eval "alld_values+=( \$$v )"
>  done
$: echo "${alld_values[@]}"
180618 180820

$: eval "alld_values=( $( sed 's/ / $/g' <<< " ${!rundate*}" ) )"

$: echo "alld_values=( $( sed 's/ / $/g' <<< " ${!rundate*}" ) )" > tmp && . tmp

【讨论】:

  • BashPitfalls #50 是相关的。 (当然,OP 的原始代码也与此冲突)。
  • 同意。事实上,代码类型取决于将其打开到特定错误的特性。更好地重构原始代码,根本不使用单个变量。
  • 我看到你已经接受了这个解决方案,但我强烈建议你考虑重构为 Charles 建议的关联数组设计...
  • 我接受了您的解决方案(最初),因为它首先发布并且有效。但是,我的开发脚本包含 Charles 的设计。我很高兴知道这是您的建议。
猜你喜欢
  • 1970-01-01
  • 2021-07-05
  • 1970-01-01
  • 2021-06-28
  • 1970-01-01
  • 1970-01-01
  • 2015-05-24
  • 1970-01-01
  • 2016-04-23
相关资源
最近更新 更多