如何使用Unix排序从tie-break组中选择最高值

时间:2017-11-17 06:59:44

标签: linux bash sorting unix awk

我有以下文本文件:

$ cat myfile.txt
foo,a,10
bar,c,33
foo,b,50
bar,a,9
foo,a,20
bar,b,20

我想要做的是按第二列和第三列(数字下降)排序,最后选择每个第二列组的顶部,结果

foo,a,20
foo,b,50
bar,c,33

我坚持这个:

$ sort -t"," -k2 -k3r   test.txt
foo,a,10
foo,a,20
bar,a,9
bar,b,20
foo,b,50
bar,c,33

做正确的方法是什么?

3 个答案:

答案 0 :(得分:6)

您的sort命令已关闭。 -k实际上需要一系列字段,因此您的-k2被解释为"对从第二个字段到行尾的所有内容进行排序,"而且它完全忽略了-k3。您必须明确范围的开始和结束位置。你也想用数字排序第三。

以下所有内容:

$ sort -t, -k2,2 -k3,3nr myfile.txt
foo,a,20
foo,a,10
bar,a,9
foo,b,50
bar,b,20
bar,c,33

现在,您要根据第二个字段选择每个组的第一行。虽然sort能够对流进行重复数据删除,但它并不够智能,无法处理这样的复杂方案。幸运的是,我们有awk:

$ sort -t, -k2,2 -k3,3nr myfile.txt | awk -F, 'x != $2 { print; x = $2 }'
foo,a,20
foo,b,50
bar,c,33

答案 1 :(得分:0)

这里有纯awk方法,

 awk -F, '{split(a[$2],b,",");if(b[3]<$3)a[$2]=$0}END{for(i in a)print [i]}' myfile.txt

简要说明,

  • split(a[$2],b,","):拆分由&#39;,&#39;分隔的每条记录,并将每个字段保存到数组b。
  • if(b[3]<$3)a[$2]=$0:比较b [3]和$ 3以确定[$ 2]是否需要更新
  • 打印最后一个数组a中的所有内容。

答案 2 :(得分:-1)

awk smauk

PURE BASH !!

regex=',(.+),'
var="xx"
for line in $(sort -t, -k2,2 -k3,3nr myfile.txt); do
  if [[ $line =~ $regex ]]; then
    bashrematch=${BASH_REMATCH[1]}
    if [[ "$var" != "$bashrematch" ]]; then
      var=$bashrematch
      echo $line
    fi
  fi
done
foo,a,20
foo,b,50
bar,c,33

只是压缩和缩小代码

r=',(.+),'; v=""; for l in $(sort -t, -k2,2 -k3,3nr myfile.txt); do [[ $l =~ $r ]] && b=${BASH_REMATCH[1]} && [ "$v" != "$b" ] && v=$b && echo $l; done
foo,a,20
foo,b,50
bar,c,33