将元素"Push"添加到Bash关联数组中

3
我正在尝试运行一个针对具有共同ID的目录中所有文件的脚本。 ls -1 *.vcf
a1.sourceA.vcf
a1.sourceB.vcf
a1.sourceC.vcf
a2.sourceA.vcf
a2.sourceB.vcf
a2.sourceC.vcf
a3.sourceA.vcf
a3.sourceC.vcf

在每种情况下,ID都位于第一个 . 之前(a1a2a3)。对于每个ID,我想要一个关联数组,其中包含该ID的所有来源,由ID作为键,例如:; a1 => [a1.sourceA.vcf, a1.sourceB.vcf, a1.sourceC.vcf]
我尝试了以下方法:
for file in $(ls *.vcf | sort)
do
  id=$(echo $file | cut -d '.' -f 1)
  vcfs[$id]+=$file

done

for i in "${!vcfs[@]}"
do
  echo "key  : $i"
  echo "value: ${vcfs[$i]}"
  echo " "
done

但是我无法弄清楚如何让它工作。在Perl中,我会在循环中将值推入数组的哈希表中: push @{$vcfs{$id}}, $file; 以便给我一个如下的数据结构:
  'a1' => [
            'a1.sourceA.vcf',
            'a1.sourceB.vcf',
            'a1.sourceC.vcf'
          ],
  'a3' => [
            'a3.sourceA.vcf',
            'a3.sourceC.vcf'
          ],
  'a2' => [
            'a2.sourceA.vcf',
            'a2.sourceB.vcf',
            'a2.sourceC.vcf'
          ]

如何在bash中实现此操作?

它停在 a3 还是你有 a4 之类的? - sjsam
1
@sjsam - 任意数量的文件 - fugu
请参考此链接 http://stackoverflow.com/a/28051297/1100158。该回答是针对嵌套列表的,但是您的解决方案应该会类似。 - ccarton
@ccarton 给你提供了一个答案。你可以将值推入关联数组,但我不会回答那个问题,因为你不想使用关联数组(每个键仅有一个值),而是要用哈希数组。Bash 不支持哈希数组,所以你需要像 ccarton 提供的大量解决方法。 - SaintHax
1个回答

2

从问题评论中给出的另一个答案

unset a1 a2 a3

function push {
    local arr_name=$1
    shift
    if [[ $(declare -p "$arr_name" 2>&1) != "declare -a "* ]]
    then
        declare -g -a "$arr_name"
    fi
    declare -n array=$arr_name
    array+=($@)
}

for file in *.vcf; do [[ -e $file ]] && push "${file%%.*}" "$file"; done

(IFS=,;echo "${a1[*]}")
(IFS=,;echo "${a2[*]}")
(IFS=,;echo "${a3[*]}")

但根据需求,也许只需要使用模式匹配就足够了。
for file in a1.*.vcf; do ... ; done

最后,不应该像其他答案中所示在for循环中使用$(ls )

为什么不应该解析ls的输出


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接