我制作了一个关联数组,如下所示。为了提供一些细节,这些键是指特定的文件,因为我将在一个更大的脚本的上下文中使用这个数组(其中包含文件的目录将是一个 getopts 参数)。
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 的变量。
我不确定以下哪种策略是最好的,我似乎无法使任何一种工作。
策略一:复制数组并修改数组?
MIN=33285268
declare -A BRAMFRACS
echo "BAMFRACS array is initialized"
BAMFRACS=("${BAMREADS[@]}")
echo ${BAMFRACS[@]} # Output: 22388955 33285268 28777698
echo ${!BAMFRACS[@]} # Output: 0 1 2
这不是我想要的钥匙。即使它有效,我也需要对所有值执行我提到的操作。
策略2:在循环第一个数组时构建第二个数组。
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
谢谢
从旧数组构建新数组:
对您的代码的评论:
您的第一个建议代码不起作用,因为它将关联数组中的值复制到新数组中。这些值会自动获取键 0、1 和 2,但不会复制原始键。如上所示,您需要逐键复制数组。这样您就可以将所需的值分配给正确的键。
您的第二个建议代码包含语法错误,因为它
=
在赋值中有空格。这就是您看到的错误的来源。variable = value
被解释为“使用操作数和”variable
执行的命令。=
value
如果您希望遍历一组路径名,请不要使用
ls
. 相反,只是做for pathname in "$BAMFILES"/*bam; do
。引用你的变量扩展。
考虑使用
printf
而不是echo
输出可变数据。有关的:
回答有关复制关联数组的更一般的问题。
当
bash
维护者在 4.0 中引入他们自己的关联数组时,他们做出了一个不幸的决定来复制 ksh93 API 而不是 zsh API。ksh93
/bash
确实支持将关联数组设置为一个整体,但它与:句法。而与
zsh
,它是(
([k]=v...)
为了兼容性,后来还添加了对 ksh93 语法的支持)。这意味着使用 ksh93 和 bash,从任意键和值列表中创建散列是非常棘手的。
使用该
zsh
语法,您只需将列表作为交替的键和值传递。例如,要复制两个关联数组:或者来自具有两列的 CSV:
或者来自键和值的数组:
使用
ksh93
/bash
语法,虽然有"${!h[@]}"
and"${h[@]}"
可以扩展为键和值列表(如"${(@k)h}"
和"${(@v)h}"
inzsh
),但没有运算符可以扩展为( in ) 所[key]=value
期望的语法中的键和值。h=(...)
"${(@kv)h}"
zsh
您可以在这些 shell 中使用的一个技巧来复制关联数组(除了在循环中复制元素),就是使用
typeset -p
.例如,复制到
zsh
's的等价物可以通过以下方式完成:h2=("${(@kv)h1}")
h1
h2
ksh93
bash
您可以将其
bash
缩短为:(虽然像在 ksh93 中一样,
typeset -A h=value
是typeset -A h=([0]=value)
in的缩写bash
,如果value
以 开头(
和结尾)
,则内容被解释为复合关联赋值,就像传递给一样eval
(即使(
被引用或某些扩展的结果))。最后,使用循环同样容易:
这应该可以做到(也可以添加额外的键值):