awk сгруппировать по нескольким столбцам и вывести максимальное значение с не-первичным ключом

Я новичок в этом сайте и пытаюсь выучить awk. Я пытаюсь найти максимальное значение field3, группируясь по field1 и распечатать все поля с максимальным значением. Поле 2 содержит время, то есть для каждого элемента 1 имеется 96 значений поля 2, поля 3 и поля 4

входной файл: (через запятую)

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[$1]<$3){
   a[$1]=$3}
}
END{
for (i in a ){
print i,a[i]
}

но это только отпечатки

item1,50
item2,30
item3,30

но мне нужно напечатать соответствующие field2 и field4 с максимальным значением, как показано в желаемом выводе. пожалуйста помоги.

3 ответа

Решение

Проблема здесь в том, что вы не сохраняете всю строку, поэтому при просмотре окончательных данных нет полных данных для печати.

Что вам нужно сделать, это использовать другой массив, скажем, data[index]=full line:

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

Или как однострочник:

$ awk 'BEGIN{FS=OFS=","} {if (a[$1]<$3) {a[$1]=$3; data[$1]=$0}} 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[$1]++'

Для этого вам необходимо:

$ cat tst.awk
BEGIN { FS="," }
!($1 in max) {
    max[$1]  = $3
    data[$1] = $0
    keys[++numKeys] = $1
}
$3 > max[$1] {
    max[$1]  = $3
    data[$1] = $0
}
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 с первого считанного значения, а не предполагать, что оно всегда будет меньше или больше некоторого произвольного значения (например, ноль или ноль, если вы пропустите !($1 in max) блок выше).

Вам нужно keys массив для сохранения порядка ввода при печати вывода. Если вы используете in вместо этого порядок вывода будет случайным.

Обратите внимание, что идиоматический синтаксис awk просто:

<condition> { <action> }

не в стиле C:

{ if ( <condition> ) { <action> } }
Другие вопросы по тегам