创建映射计数

时间:2014-05-10 23:57:04

标签: bash shell

我有两列的数据

Id Users
123 2
123 1
234 5
234 6
34 3

我想从这样的给定数据创建这个计数映射

123 3
234 11
34 3

我怎样才能在bash中做到这一点?

3 个答案:

答案 0 :(得分:1)

您必须使用关联数组,例如

declare -A newmap
newmap["123"]=2
newmap["123"]=$(( ${newmap["123"]} + 1))

显然你必须遍历你的输入,查看条目是否存在然后添加到它,否则初始化它

答案 1 :(得分:0)

使用awk会更容易。

解决方案1:不希望对文件进行排序。将整个文件存储在内存中

awk '{a[$1]+=$2}END{for(x in a) print x,a[x]}' file 
34 3
234 11
123 3

我们在这里做的是将第一列用作key并将第二列添加为值。在END块中,我们遍历数组并打印key=value对。

如果您的输入文件中有Id Users行,并希望将其从输出中排除,请添加NR>1条件:

awk 'NR>1{a[$1]+=$2}END{for(x in a) print x,a[x]}' file

NR>1告诉awk跳过第一行。 NR包含行号,因此我们指示awk从第二行开始创建数组。


解决方案2:预期要排序的文件。不将文件存储在内存中。

awk '$1!=prev && NR>1{print prev,sum}{prev=$1; sum+=$2}END{print prev,sum}' file
123 3
234 14
34 17

如果您的输入文件中有Id Users行,并希望将其从输出中排除,请添加NR>1条件:

awk '$1!=prev && NR>2{print prev, sum}NR>1{prev = $1; sum+=$2}END{print prev, sum}' ff
123 3
234 14
34 17

答案 2 :(得分:0)

Bash(4.0+)解决方案:

declare -Ai count

while read a b ; do
  count[$a]+=b
done < "$infile"

for idx in ${!count[@]}; do
  echo  "${idx} ${count[$idx]}"
done

对于排序的输出,最后一行应为

done | sort -n