максимална и минимална стойност на съвпадащите линии

Бих искал да преброя минималната и максималната стойност на моя съвпадащ ред във файла:

Аз имам:

xxx 5
xxx 0  
xxx 10  
yyy 1  
yyy 5  
yyy 10

И бих искал да имам на изхода:

xxx 0 10
yyy 1 10

Минимална и максимална стойност за xxx и yyy съвпадения.

Моят код е:

awk '{if(min==""){min=max=$2}
      if($2>max) {max=$2}
      if($2<min) {min=$2}
      n[$1]++}
      END {for (l in n) {print l "\t" min[l] }}' inputfile

Много благодаря за всяка помощ.


person Paul    schedule 07.10.2014    source източник
comment
И така, каква е твоята грешка? Има ли дори грешка?   -  person APerson    schedule 07.10.2014


Отговори (1)


Имате нужда от масиви за това:

awk '!($1 in min) {min[$1]=$2; max[$1]=$2}
     {max[$1]=(max[$1]<$2?$2:max[$1])
      min[$1]=(min[$1]>$2?$2:min[$1])}
      END { for (i in max) print i, min[i], max[i]}' file

Обяснение

max[] съдържа максималната стойност за всяка стойност. Същото важи и за min[].

  • !($1 in min) {min[$1]=$2; max[$1]=$2} ако няма min за текущо поле, инициализирайте ги.
  • max[$1]=(max[$1]<$2?$2:max[$1]) ако текущото 2-ро поле е по-голямо от съответния максимум за 1-вата колона, заменете.
  • min[$1]=(min[$1]>$2?$2:min[$1]) същото с минимума.
  • END { for (i in max) print i, min[i], max[i]} прегледайте резултатите и ги отпечатайте.

Тест

$ awk '!($1 in min) {min[$1]=$2; max[$1]=$2} {max[$1]=(max[$1]<$2?$2:max[$1]); min[$1]=(min[$1]>$2?$2:min[$1])} END { for (i in max) print i, min[i], max[i]}' a
yyy 1 10
xxx 0 10

Трябва да дефинираме min и max, когато четем първия ред!

$ cat a
x -1
x 0
y 1
x -3
$ awk '!($1 in min) {min[$1]=$2; max[$1]=$2} {max[$1]=(max[$1]<$2?$2:max[$1]); min[$1]=(min[$1]>$2?$2:min[$1])} END { for (i in max) print i, min[i], max[i]}' a
x -3 0
y 1 1
person fedorqui 'SO stop harming'    schedule 07.10.2014
comment
Може също да използва getline, ако паметта е ограничена. - person ; 07.10.2014
comment
Не мисля, че използването на getline е необходимо тук, @Jidder, как бихте приложили това? С масиви трябва да е достатъчно. Има добра статия от Ед Мортън, която говори за това, но не мога да я намеря сега. - person fedorqui 'SO stop harming'; 07.10.2014
comment
Забележете също, че актуализирах първия си отговор, беше малко грешен. - person fedorqui 'SO stop harming'; 07.10.2014
comment
@fedorqui Четейки това отново, не, не мисля, че е така. За да го приложи обаче, за всеки нов $1 той ще прочете файла и ще намери min и max за този $1 и ще ги съхрани във временна променлива във функция, след това ще отпечата, след което ще може да пропусне всички останали от този $1. Това обаче е ненужно сложно за този въпрос и дори не знам защо го предложих. - person ; 07.10.2014
comment
Няма проблем, @Jidder! Винаги е добре да преосмислим какво правим и как го правим. Благодаря за коментара :) - person fedorqui 'SO stop harming'; 07.10.2014
comment
@fedorqui Опитах първия ти пост и работи много добре. Второто имам някакъв странен резултат. Оригиналът беше: awk '{max[$4]=(max[$4]‹$8?$8:max[$4]); min[$4]=(!(min[$4]) || min[$4]›$8?$8:min[$4])}END {for (i in max) print i \t min[i] \t max[ i]}' input_file - person Paul; 07.10.2014
comment
@Incorigible да, вярно, първият код не беше правилен. Ето защо актуализирах. Благодаря, че ме уведомихте. - person fedorqui 'SO stop harming'; 07.10.2014
comment
@fedorqui Не, мисля, че първият код беше правилен. Новият ми даде странен резултат :-( Просто го потвърждавам.. - person Paul; 07.10.2014
comment
@Incorigible, странно... второто ми работи добре за всеки примерен вход, който използвам. Между другото, винаги можете да видите предишните ревизии в stackoverflow.com/posts/26236749/revisions - person fedorqui 'SO stop harming'; 07.10.2014
comment
@fedorqui, ако 0 е най-голямото число, тогава max ще се провали поради същата причина, поради която min. - person ; 07.10.2014
comment
@Jidder не. !(var) е просто вярно, ако var не е дефинирано или е 0. Можете да тествате така: запишете от -10 до 10 във файл: seq -10 10 >a. Проверете кога условието е изпълнено: awk '!$1 {print "it is empty or 0:", $1}' a - person fedorqui 'SO stop harming'; 07.10.2014
comment
Прочетох го погрешно (отново! съжалявам), но проблемът, който изпитах, беше причинен от това, че нулата е най-голямото число, както е посочено в следващия коментар. Благодаря все пак за бързия отговор :) - person ; 07.10.2014
comment
@Jidder съжалявам, имах предвид предишния ви коментар. Относно нулата си прав. Току-що актуализирах, дефинирайки стойностите при първото четене. Благодаря! - person fedorqui 'SO stop harming'; 07.10.2014
comment
@fedorqui Да, съжалявам за грешката ми.. Първият код се провали, ако стойността ми е нула.. Новият актуализиран код работи перфектно със стойност 0 (нулата е най-ниската ми стойност в моите файлове).. Много благодаря за отделеното време и помощта! Научих нещо ново! - person Paul; 07.10.2014