bash:选择最大时间戳的分组或合并行

时间:2015-12-17 11:13:14

标签: bash sorting merge group-by max

我有这样的输入:

A 05 something
B 03 something1
A 02 something43
A 01 somethingelse
C 03 something2
B 10 something
C 01 somethingagain

我想输出:

A 05 something
B 10 something
C 03 something2

这是我按第一个字段分组并选择最大数字。在我的情况下,该数字是固定长度的时间戳,因此您可以使用字母排序来获得最大的时间戳。我更喜欢使用一些命令行工具,我想它可以通过一些简单的方式完成,但直到现在还没有成功。请不要正则表达式地狱,更可读,更好:)

3 个答案:

答案 0 :(得分:2)

只需排序两次:

< input sort -rk2,2 | sort -k1,1 -u

第一列排序按第二列排序(-r表示反转),第二列按第一列和唯一排序排序(-u)。

答案 1 :(得分:1)

您可以使用awk将结果存储在数组中:

cat input | awk '{if (a[$1] < $2) a[$1]=$2;} END {for (i in a) print i, a[i];}' 
如果第一列$ 2是第二列,则

$ 1。 这一部分:{if (a[$1] < $2) a[$1]=$2;}只是在数值大于已经存储在数组中的值时(默认为零),用当前值更新数组。

此部分END {for (i in a) print i, a[i];}'在输入耗尽后运行,​​只需打印矢量。

更新:要回答OP的更新:使用另一个向量来存储整行:

cat input | awk '{if (a[$1] < $2) {a[$1]=$2; b[$1]=$0;}} END {for (i in a) print b[i];}' 

答案 2 :(得分:1)

您可以按反向升序排序第二个字段,按升序排序第一个字段,并使用awk仅打印键列的第一个值:

sort -k1,1 -k2r,2 input.txt | awk '{ if (! F[$1]) print; F[$1]=1  }'

如果awk脚本没有在第一列中看到密钥,则会打印整行。然后它会记住第一列中的键,这样如果再次看到它就不会被打印出来。