首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于另一个关联数组生成关联数组

基于另一个关联数组生成关联数组
EN

Unix & Linux用户
提问于 2018-08-24 11:54:37
回答 3查看 7.5K关注 0票数 4

我创建了一个关联数组,如下所示。为了给出一些细节,键引用了特定的文件,因为我将在更大的脚本中使用这个数组(其中包含文件的目录将是getopts参数)。

代码语言:javascript
复制
declare -A BAMREADS
echo "BAMREADS array is initialized"

BAMREADS[../data/file1.bam]=33285268
BAMREADS[../data/file2.bam]=28777698
BAMREADS[../data/file3.bam]=22388955

echo ${BAMREADS[@]}  # Output: 22388955 33285268 28777698
echo ${!BAMREADS[@]} # Output: ../data/file1.bam ../data/file2.bam ../data/file3.bam

到目前为止,这个数组的行为似乎与我预期的一样。现在,我想在这个数组的基础上构建另一个关联数组。具体而言:我的第二个数组将具有与第一个数组相同的键,但我希望将值除以一个名为$MIN的变量。

我不知道以下哪一种策略是最好的,我似乎无法让这两种策略发挥作用。

Strategy 1:复制数组并修改数组?

代码语言:javascript
复制
MIN=33285268

declare -A BRAMFRACS
echo "BAMFRACS array is initialized"
BAMFRACS=("${BAMREADS[@]}")

echo ${BAMFRACS[@]}  # Output: 22388955 33285268 28777698
echo ${!BAMFRACS[@]} # Output: 0 1 2

这不是我想要的钥匙。即使它有效,我也需要对所有的值执行我提到的操作。

Stragegy 2:在遍历第一个数组时构建第二个数组。

代码语言:javascript
复制
MIN=33285268

declare -A BRAMFRACS
echo "BAMFRACS array is initialized"

for i in $(ls $BAMFILES/*bam)
do
    echo $i
    echo ${BAMREADS[$i]}
    BAMFRACS[$i] = ${BAMREADS[$i]} 
done

echo ${BAMFRACS[@]}
echo ${!BAMFRACS[@]}


#When I run this, I get the following error which I am unsure how to solve:

../data/file1.bam
33285268
script.bash: line 108: BAMFRACS[../data/file1.bam]: No such file or directory
../data/file2.bam
28777698
script.bash: line 108: BAMFRACS[../data/file2.bam]: No such file or directory
../data/file3.bam
22388955
script.bash: line 108: BAMFRACS[../data/file3.bam]: No such file or directory

谢谢

EN

回答 3

Unix & Linux用户

回答已采纳

发布于 2018-08-24 12:02:45

从旧数组构建新数组:

代码语言:javascript
复制
MIN=33285268

declare -A BRAMFRACS
for key in "${!BAMREADS[@]}"; do
    BRAMFRACS[$key]=$(( ${BAMREADS[$key]} / MIN ))
done

对您的代码的评论:

  • 您的第一个建议代码无法工作,因为它将值从关联数组复制到新数组。这些值自动获得键0、1和2,但未复制原始键。如我前面所示,您需要按键复制数组键。通过这种方式,您可以将想要的值分配给正确的键。
  • 第二个建议的代码包含一个语法错误,因为它在赋值中的=周围有空格。这就是你所看到的错误的来源。variable = value被解释为“使用操作数=value执行的命令variable”。
  • 如果希望迭代一组路径名,请不要使用ls。相反,只需执行for pathname in "$BAMFILES"/*bam; do
  • 引用变量展开。
  • 考虑使用printf而不是echo输出变量数据。

相关信息:

票数 7
EN

Unix & Linux用户

发布于 2018-08-24 14:19:48

以回答有关复制关联数组的更一般问题。

bash维护者在4.0中引入他们自己的关联数组时,他们做出了复制ksh93 API而不是zsh API的不幸决定。

ksh93/bash确实支持将关联数组设置为一个整体,但它使用的是:

代码语言:javascript
复制
hash=([k1]=v1 [k2]=v2)

语法。对于zsh,它是

代码语言:javascript
复制
hash=(k1 v1 k2 v2)

(为了兼容性,稍后还添加了对([k]=v...) ksh93语法的支持)。

但这意味着,使用ksh93和bash,从任意的键和值列表创建散列是非常困难的。

使用zsh语法,只需将列表作为交替键和值传递。例如,要复制两个关联数组:

代码语言:javascript
复制
h2=("${(@kv)h1}")

或来自有两列的CSV:

代码语言:javascript
复制
IFS=或来自键和值数组:h=("${(@)keys:^values}")使用ksh93/bash语法,虽然有"${!h[@]}"和"${h[@]}"扩展到键和值的列表(比如zsh中的"${(@k)h}"和"${(@v)h}" ),但是在h=(...)所期望的[key]=value语法( "${(@kv)h}"在d21中)中,没有操作符可以同时展开键和值。但是,在这些shell中复制关联数组(除了在循环中复制元素之外)的一个技巧是使用typeset -p的输出。例如,等效于zsh's h2=("${(@kv)h1}")将h1复制到h2中,可以在ksh93或bash中使用:h1_definition=$(typeset -p h1) &&
  eval "typeset -A h2=${h1_definition#*=}"使用bash,您可以将其缩短为:h1_definition=$(typeset -p h1) &&
  typeset -A h2="${h1_definition#*=}"(与ksh93类似,typeset -A h=value是bash中typeset -A h=([0]=value)的缩写,如果value以(开头,以)结尾,则内容被解释为复合关联赋值,就好像传递给eval (即使引用(或某些扩展的结果))。最后,使用循环也同样容易:for k in "${!h1[@]}"; do h2[$k]=${h1[$k]}; done\n,'; h=($(

或来自键和值数组:

A10

使用D11/D12语法,虽然有D13和D14扩展到键和值的列表(比如D17中的D15和D16 ),但是在D19所期望的D18语法( D20在d21中)中,没有操作符可以同时展开键和值。

但是,在这些shell中复制关联数组(除了在循环中复制元素之外)的一个技巧是使用D22的输出。

例如,等效于D23's D24将D25复制到D26中,可以在D27或D28中使用:

A29

使用D30,您可以将其缩短为:

A31

(与ksh93类似,D32是D34中D33的缩写,如果D35以D36开头,以D37结尾,则内容被解释为复合关联赋值,就好像传递给D38 (即使引用D39或某些扩展的结果))。

最后,使用循环也同样容易:

A40

票数 7
EN

Unix & Linux用户

发布于 2020-05-06 23:26:24

这应该可以做到(还可以添加额外的键值):

代码语言:javascript
复制
declare -A origDict=( [keya]=value_a [keyb]=value_b [keyc]=value_c )
declare -a newDict=( echo ${origDict[*]} [keynew]=new_value )
票数 -3
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/464626

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档