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> } }