如何使用Unixsorting从tie-break组中挑选最高分值

我有以下文本文件:

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

我想要做的是按第二列和第三(数字降序)sorting,最后select每个第二列组的顶部,导致

 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 

什么是正确的方法来做到这一点?

你的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 

这是纯粹的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,",") :分隔由','分隔的每个记录,并将每个字段保存到数组b。
  • if(b[3]<$3)a[$2]=$0 :比较b [3]和$ 3以确定是否需要更新[$ 2]
  • 最后打印数组a中的所有内容。

awk smauk

纯粹的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