我有以下文本文件:
$ 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
做正确的方法是什么?
答案 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]是否需要更新答案 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