我的csv文件中的第二列有重复项。我想根据这些重复添加第1列的相关值。Bash - 根据列在行中添加值
例CSV:
56, cc=DK
49, cc=US
34, cc=GB
32, cc=DE
32, cc=NZ
31, cc=DK
31, cc=GB
31, cc=GB
结果举例:
96, cc=GB # where 96 = 34+31+31
87, cc=DK # where 87 = 56+31
32, cc=DE
32, cc=NZ
我的csv文件中的第二列有重复项。我想根据这些重复添加第1列的相关值。Bash - 根据列在行中添加值
例CSV:
56, cc=DK
49, cc=US
34, cc=GB
32, cc=DE
32, cc=NZ
31, cc=DK
31, cc=GB
31, cc=GB
结果举例:
96, cc=GB # where 96 = 34+31+31
87, cc=DK # where 87 = 56+31
32, cc=DE
32, cc=NZ
可以在awk
使用关联数组:
awk '{s[$2]+=$1}END{for(k in s)print s[k]", ",k}' inFile
拓展上,对于可读性,使用sum/key
,而不是s/k
:
{ # Do for each line.
sum[$2] += $1 # Add first field to accumulator,
# indexed by second field.
# initial value is zero.
}
END { # Do this bit when whole file processed.
for (key in sum) # For each key like cc=US:
print sum[key] ", " key # Output the sum and key.
}
这里有我的盒子样品运行:
pax$ echo;echo '56, cc=DK
49, cc=US
34, cc=GB
32, cc=DE
32, cc=NZ
31, cc=DK
31, cc=GB
31, cc=GB' | awk '{s[$2]+=$1}END{for(k in s)print s[k]", "k}'
32, cc=DE
96, cc=GB
32, cc=NZ
49, cc=US
87, cc=DK
这工作尽管第一列的形式999,
的(注意最后的逗号),只是因为awk
,当在数字上下文中计算字符串,只使用在该上下文中有效的前缀。因此45xyzzy
将变成45
,更重要的是,49,
变成49
。
你也可以改变FS而不是gsub(这是没有意义的,因为你正在改变'',并且可以使用sub,因为它是$ 1,因为它默认为$ 0)根据我的代码对这个问题的评论。 – 2015-04-01 08:13:02
@JID,我确实想到了,但事实证明gsub/sub甚至不需要,所以我删除了它。 – paxdiablo 2015-04-01 08:26:23
哦,是的,你可以削减2个字符,因为不需要'(k in s)'之后的'{}'。 – 2015-04-01 08:27:45
Perl的溶液:
perl -ane '$h{ $F[1] } += $F[0] }{ print "$h{$_}\t$_\n" for keys %h' input.csv
说明:
-n
处理由线-a
输入线按空白进行分割输入线到@F阵列}{
(称为“爱斯基摩人的问候语”)分开什么是从每行代码(-n
)执行整个输入被处理这是确定使用awk
这种简单的任务后运行,但如果你有很多类似的任务,你可能需要在将来改变它,很容易搞砸了。
由于这是典型的数据库问题,请考虑使用sqlite
。
您可以:
添加行名称和删除多余的空格:
$ cat <(echo "num, name") originalInput.txt | tr -d ' ' > input.csv
导入数据到临时的SQLite数据库:从数据库
$ sqlite3 --batch temp.db <<EOF!
.mode csv
.import input.csv input
EOF!
选择:
$sqlite3 temp.db 'SELECT sum(num), name FROM input GROUP BY name'
32|cc=DE
87|cc=DK
96|cc=GB
32|cc=NZ
49|cc=US
它稍微多一点的代码,并使用外部sqlite3
命令,但它是显著不容易出错多灵活。你可以很容易地加入几个CSV文件,使用奇特的排序,等等。
此外,假设你自己在六个月后查看代码,试图快速了解它的功能。
您的最后一条陈述取决于您对该语言的熟悉程度,需要更长的时间才能确定您的代码与上面的awk相比有多长。这只是看起来像是过度杀伤。不但你必须安装一个外部程序(每个人都可能因为某种原因无法完成)你还必须编辑原始数据,创建一个数据库,然后得到输出不再以CSV格式。如果你想要比awk更强大的方法,你可以使用一个csv解析器。 – 2015-04-01 09:32:23
@JID,“可以使用awk,在这里,但*如果你有一堆类似的任务,请考虑* sqlite”。我在制作中看到过数百个这样的awk/sed/perl/* sh脚本,并且在很多情况下,它并不适合这项工作。顺便说一句,csv解析器不会为你做聚合。 – 2015-04-01 10:38:43
我也见过很多'魔术awk/sed/perl/* sh脚本',如果它们没有被写得很糟糕,并且你对这门语言有一个基本的理解,那么你就不会立即理解正在做什么。另外我的意思是在python或perl中使用csv解析器,阅读它可能应该已经更清楚了。 – 2015-04-01 11:06:12
'awk -F,'{a [$ 2] + = $ 1} END {for(i in a)print a [i] FS i}'file'。你也离开了美国的输出 – 2015-04-01 08:02:40