awk 按多列分组并使用非主键打印最大值

awk group by multiple columns and print max value with non-primary key

我是这个网站的新手,正在尝试学习 awk。我试图找到 field3 的最大值,按 field1 分组并打印所有具有最大值的字段。字段 2 包含时间,这意味着对于每个 item1,字段 2、字段 3 和字段 4

有 96 个值

输入文件:(逗号分隔)

item1,00:15,10,30
item2,00:45,20,45
item2,12:15,30,45
item1,00:30,20,56
item3,23:00,40,44
item1,12:45,50,55
item3,11:15,30,45

期望的输出:

item1,12:45,50,55
item2,12:15,30,45
item3,11:15,30,45

到目前为止我尝试了什么:

BEGIN{
FS=OFS=","}
{
if (a[]<){
   a[]=}
}
END{
for (i in a ){
print i,a[i]
}

但这只会打印

item1,50
item2,30
item3,30

但我需要打印相应的 field2 和 field4 以及所需输出中显示的最大值。请帮忙

这里的问题是你没有存储整行,所以当你检查最后的数据时,没有完整的数据要打印。

你需要做的是使用另一个数组,比如 data[index]=full line:

BEGIN{
FS=OFS=","}
{
 if (a[]<){
   a[]=
   data[]=[=10=]}       # store it here!
}
END {
   for (i in a )
       print data[i]  # print it here
}

或作为单线:

$ awk 'BEGIN{FS=OFS=","} {if (a[]<) {a[]=; data[]=[=11=]}} END{for (i in a) print data[i]}' file
item1,12:45,50,55
item2,12:15,30,45
item3,23:00,40,44

sort 命令的帮助下:

sort -t, -k1,1 -k3,3nr file | awk -F, '!seen[]++'

要稳健地完成这项工作,您需要:

$ cat tst.awk
BEGIN { FS="," }
!( in max) {
    max[]  = 
    data[] = [=10=]
    keys[++numKeys] = 
}
 > max[] {
    max[]  = 
    data[] = [=10=]
}
END {
    for (keyNr=1; keyNr<=numKeys; keyNr++) {
        print data[keys[keyNr]]
    }
}

$ awk -f tst.awk file
item1,12:45,50,55
item2,12:15,30,45
item3,23:00,40,44

在进行 min/max 计算时,您应该始终使用读取的第一个值作为 min/max 值的种子,而不是假设它总是小于或大于某个任意值(例如零或-null 如果你跳过上面的 !( in max) 块)。

您需要 keys 数组来在打印输出时保留输入顺序。如果您使用 in,那么输出顺序将是随机的。

请注意,awk 的惯用语法很简单:

<condition> { <action> }

非 C 风格:

{ if ( <condition> ) { <action> } }