AWK, Perl или Shell? Уникальные строки и их максимальные значения из файла данных с 3 столбцами - PullRequest
2 голосов
/ 22 февраля 2012

У меня есть файл, содержащий данные примерно так:

2012-01-02 GREEN 4
2012-01-02 GREEN 6
2012-01-02 GREEN 7
2012-01-02 BLUE 4
2012-01-02 BLUE 3
2012-01-02 GREEN 4
2012-01-02 RED 4
2012-01-02 RED 8
2012-01-02 GREEN 4
2012-01-02 YELLOW 5
2012-01-02 YELLOW 2

Я не всегда могу предсказать, какими будут строки во втором столбце (поэтому в приведенном выше примере есть цвета, но файл данных может содержать любую строку во втором столбце). Однако в третьем столбце всегда есть число (для которого я хочу получить максимальное значение для произвольной строки во втором столбце). Может ли awk:

  1. Вытащить каждую из уникальных строк в столбце 2?
  2. Для каждой из уникальных строк получить максимальное связанное значение (поэтому, используя приведенное выше, вы получите следующее):

    2012-01-02 GREEN 7
    2012-01-02 BLUE 4
    2012-01-02 RED 8
    2012-01-02 YELLOW 5
    

или это будет проще с Perl (или даже с shell)? любые примеры кода очень ценятся!

Ответы [ 4 ]

7 голосов
/ 22 февраля 2012
$ sort -k2,2 -k3,3nr input.txt | awk 'x!=$2{x=$2;print}'
2012-01-02 BLUE 4
2012-01-02 GREEN 7
2012-01-02 RED 8
2012-01-02 YELLOW 5
5 голосов
/ 22 февраля 2012

Вы можете сделать это в perl или awk практически с той же техникой (используя ассоциативные массивы).

Вот пример awk. max содержит (текущий) максимум для данного «ключа», lines строка, на которой произошел этот максимум.

max[$2] < $3 {
  max[$2] = $3
  lines[$2] = $0
}
END {
  for (x in lines)
    print lines[x]
}
2 голосов
/ 22 февраля 2012

Это может работать для вас:

cat -n file | sort -ruk2 | sort -uk2,3 | sort -n | cut -f2
2012-01-02 GREEN 7
2012-01-02 BLUE 4
2012-01-02 RED 8
2012-01-02 YELLOW 5

, если заказ не является проблемой:

sort -k1,2 -k3nr file | sort -uk1,2 
2012-01-02 BLUE 4
2012-01-02 GREEN 7
2012-01-02 RED 8
2012-01-02 YELLOW 5
1 голос
/ 23 февраля 2012

Была похожая идея с использованием массивов

awk '{i=$1" "$2;if($3>c[i]){c[i]=$3}}END{for(a in c){print a,c[a]}}' colors.txt
2012-01-02 RED 8
2012-01-02 YELLOW 5
2012-01-02 GREEN 7
2012-01-02 BLUE 4

и Perl One

perl -lne '/^(.*)(\d+)$/;$x{$1}=$2 if $2>$x{$1};END{for(sort keys %x){print $_,$x{$_}}}' colors.txt
2012-01-02 BLUE 4
2012-01-02 GREEN 7
2012-01-02 RED 8
2012-01-02 YELLOW 5
...