Bash CSV排序和唯一性

时间:2013-04-23 13:52:50

标签: linux bash sorting awk unique

Linux问题:我的CSV文件data.csv包含以下字段和值

KEY,LEVEL,DATA
2.456,2,aaa
2.456,1,zzz
0.867,2,bbb
9.775,4,ddd
0.867,1,ccc
2.456,0,ttt 
...

字段KEY是浮点值,而LEVEL是整数。我知道第一个字段可以有重复的值,也可以有第二个字段,但是如果你把它们放在一起就有一对独特的值。

我想要做的是根据列KEY对文件进行排序,然后对于KEY下的每个唯一值,只保留LEVEL下值较高的行。 排序不是问题:

$> sort -t, -k1,2 data.csv  # fields: KEY,LEVEL,DATA
0.867,1,ccc
0.867,2,bbb
2.456,0,ttt
2.456,1,zzz
2.456,2,aaa
9.775,4,ddd
...

但是我怎样才能过滤行以便得到我想要的东西,即:

0.867,2,bbb
2.456,2,aaa
9.775,4,ddd
...

有没有办法使用sortuniqawk等命令行工具来实现?提前致谢

3 个答案:

答案 0 :(得分:4)

试试这一行:

your sort...|awk -F, 'k&&k!=$1{print p}{p=$0;k=$1}END{print p}'

输出:

kent$  echo "0.867,1,bbb
0.867,2,ccc
2.456,0,ttt
2.456,1,zzz
2.456,2,aaa
9.775,4,ddd"|awk -F, 'k&&k!=$1{print p}{p=$0;k=$1}END{print p}'
0.867,2,ccc
2.456,2,aaa
9.775,4,ddd

这个想法是,因为您的文件已经排序,只需从顶部浏览文件/输入,如果第一列(KEY)发生变化,则打印最后一行,这是{{的最高值最后LEVEL

的1}}

尝试使用您的真实数据,它应该可以正常工作。

整个逻辑(有你的排序)也可以通过awk在单个进程中完成。

答案 1 :(得分:3)

使用:

$> sort -r data.csv | uniq -w 5 | sort

鉴于您的浮动格式为“0.000” - “9.999”

答案 2 :(得分:0)

Perl解决方案:

perl -aF, -ne '$h{$F[0]} = [@F[1,2]] if $F[1] > $h{$F[0]}[0]
               }{
               print join ",", $_, @{$h{$_}} for sort {$a<=>$b} keys %h' data.csv

请注意,结果与您请求的结果不同,第一行包含bbb,而不是ccc