mf9*_*f94 3 bash associative-array
我制作了一个关联数组,如下所示。为了提供一些详细信息,键是指特定文件,因为我将在较大脚本的上下文中使用此数组(其中包含文件的目录将是 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
Run Code Online (Sandbox Code Playgroud)
到目前为止,这个数组的行为似乎符合我的预期。现在,我想基于这个数组构建另一个关联数组。具体来说:我的第二个数组将具有与第一个相同的键,但我想将这些值除以名为 $MIN 的变量。
我不确定以下哪种策略是最好的,而且我似乎无法使任何一种工作。
策略1:复制数组并修改数组?
MIN=33285268
declare -A BRAMFRACS
echo "BAMFRACS array is initialized"
BAMFRACS=("${BAMREADS[@]}")
echo ${BAMFRACS[@]} # Output: 22388955 33285268 28777698
echo ${!BAMFRACS[@]} # Output: 0 1 2
Run Code Online (Sandbox Code Playgroud)
这不是我想要的钥匙。即使它有效,我也需要对所有值执行我提到的操作。
策略 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
Run Code Online (Sandbox Code Playgroud)
谢谢
回答关于复制关联数组的更普遍的问题。
当bash维护者在 4.0 中引入自己的关联数组时,他们做出了一个不幸的决定,即复制 ksh93 API 而不是 zsh API。
ksh93/bash确实支持将关联数组设置为一个整体,但它与:
hash=([k1]=v1 [k2]=v2)
Run Code Online (Sandbox Code Playgroud)
句法。使用 时zsh,它是
hash=(k1 v1 k2 v2)
Run Code Online (Sandbox Code Playgroud)
(([k]=v...)为了兼容性,稍后还添加了对ksh93 语法的支持)。
不过,这意味着使用 ksh93 和 bash,从任意键和值列表中创建散列是非常棘手的。
使用zsh语法,您只需要将列表作为交替键和值传递。例如,要复制两个关联数组:
h2=("${(@kv)h1}")
Run Code Online (Sandbox Code Playgroud)
或者来自包含两列的 CSV:
IFS=$'\n,'; h=($(<file.csv))
Run Code Online (Sandbox Code Playgroud)
或者来自键和值的数组:
h=("${(@)keys:^values}")
Run Code Online (Sandbox Code Playgroud)
使用ksh93/bash语法,虽然有"${!h[@]}"and"${h[@]}"扩展到键和值列表(如"${(@k)h}"and "${(@v)h}"in zsh),但没有运算符可以扩展到(in )[key]=value预期的语法中的键和值。h=(...)"${(@kv)h}"zsh
您可以在这些 shell 中使用的一个技巧来复制关联数组(除了在循环中复制元素),是使用typeset -p.
举例来说,相当于zsh的h2=("${(@kv)h1}")复制h1到h2中可以做ksh93或bash用:
h1_definition=$(typeset -p h1) &&
eval "typeset -A h2=${h1_definition#*=}"
Run Code Online (Sandbox Code Playgroud)
与bash可以缩短到:
h1_definition=$(typeset -p h1) &&
typeset -A h2="${h1_definition#*=}"
Run Code Online (Sandbox Code Playgroud)
(虽然像在ksh93的,typeset -A h=value是短于typeset -A h=([0]=value)在bash,如果value与开始(和结束用),然后仿佛传递到内容被解释为化合物缔分配eval(即使该(被引用或一些扩展的结果))。
最后,使用循环也很容易:
for k in "${!h1[@]}"; do h2[$k]=${h1[$k]}; done
Run Code Online (Sandbox Code Playgroud)
从旧数组构建新数组:
MIN=33285268
declare -A BRAMFRACS
for key in "${!BAMREADS[@]}"; do
BRAMFRACS[$key]=$(( ${BAMREADS[$key]} / MIN ))
done
Run Code Online (Sandbox Code Playgroud)
对您的代码的评论:
您的第一个建议代码不起作用,因为它将值从关联数组复制到新数组。这些值会自动获取键 0、1 和 2,但不会复制原始键。如上所示,您需要逐个键复制数组。这样您就可以将所需的值分配给正确的键。
您的第二个建议代码包含一个语法错误,因为它=在赋值中有空格。这就是您看到的错误的来源。 variable = value被解释为“variable使用操作数=和value”执行的命令。
如果您希望迭代一组路径名,请不要使用ls. 而只是做for pathname in "$BAMFILES"/*bam; do。
引用你的变量扩展。
考虑使用printf而不是echo输出可变数据。
有关的:
| 归档时间: |
|
| 查看次数: |
4522 次 |
| 最近记录: |