使用awk在每一行中找到前5个最大值

时间:2016-07-28 20:45:56

标签: awk gawk

我正在尝试阅读如下文本文件

word 1 2 3 4 5 6 7 8 9 10
hello 0.2 0.3 0.5 0.1 0.7 0.8 0.6 0.1 0.9

我想打印“hello”这个词,以及最大5个值以及它们所在的列数,就像使用awk一样:

hello 10 0.9 7 0.8 6 0.7 8 0.6 3 0.5

我想过像awk '{ for (i=1; i <= 10; i++) a[$i]=$i};END{c=asort(a)?? for(i in a)print i,a[i]??}'这样的东西,但我想在每一行都打印出来。

4 个答案:

答案 0 :(得分:1)

使用GNU awk 4. * for sorted_in:

$ cat tst.awk
BEGIN { PROCINFO["sorted_in"] = "@val_num_desc" }
NR>1 {
    split($0,a)
    printf "%s", a[1]
    delete a[1]
    for (i in a) {
        printf " %d %s", i, a[i]
        if (++c == 5) {
            c=0
            break
        }
    }
    print ""
}

$ awk -f tst.awk file
hello 10 0.9 7 0.8 6 0.7 8 0.6 4 0.5

答案 1 :(得分:0)

你声明 [你]想要在每行读取,所以读取的记录没有限制:

$ awk '{delete a; for(i=2; i<=NF; i++) {a[$i]=$i; b[$i]=i}; n=asort(a); printf "%s: ",$1; for(i=n; i>n-(n>=5?5:n); i--) printf "%s %s ", b[a[i]], a[i]; printf "\n"}' test.in
word: 11 10 10 9 9 8 8 7 7 6 
hello: 10 0.9 7 0.8 6 0.7 8 0.6 4 0.5

Walk-thru版本:

{
  delete a                        # delete the array before each record
  for(i=2; i<=NF; i++) {          # from the second field to the last
    a[$i]=$i                      # set field to array index and value
    b[$i]=i                       # remember the field number 
  }
  n=asort(a)                      # sort the a array
  printf "%s: ",$1                # print the record identifier ie. the first field
  for(i=n; i>n-(n>=5?5:n); i--)   # for the 5 (or value count) biggest values
    printf "%s %s", b[a[i]], a[i] # print them out
  printf "\n"                     # enter after each record
}

如果值重复,则仅打印一次。

答案 2 :(得分:0)

这是一个awk辅助的Unix工具集解决方案。

$ awk -v RS=" " 'NR==1; NR>1{print NR, $0 | "sort -k2nr"} ' file | head -6 | xargs
hello 10 0.9 7 0.8 6 0.7 8 0.6 4 0.5

我认为你的预期输出有一些拼写错误。

答案 3 :(得分:0)

使用Perl

$ cat cloudy.txt
word 1 2 3 4 5 6 7 8 9 10
hello 0.2 0.3 0.5 0.1 0.7 0.8 0.6 0.1 0.9

$ perl -lane '%kv=();%kv=map{ $_=>$F[$_] } 1..$#F; printf("$F[0] ");$i=0; for $x (reverse sort {$a <=> $b} values %kv) { @y=grep $x eq $kv{$_}, (keys %kv); printf("%d %.1f
 ",$y[0]+1,$x) if $i++ <5 } print "" ' cloudy.txt
word 11 10.0 10 9.0 9 8.0 8 7.0 7 6.0
hello 10 0.9 7 0.8 6 0.7 8 0.6 4 0.5

$