AWK - 根据分数打印 Select 行

AWK - Select lines to print according to score

我有一个制表符分隔的文件,其中包含一系列带有相关分数的引理。 该文件包含 5 列,第一列是引理,第三列是包含分数的列。我需要做的是在不重复引理时按原样打印该行,并在重复引理时打印得分最高的行。

Lemma    ---    Score    ---    ---
cserép    06a    55    6    bueno
darázs    05     38    1    bueno
dél    06a    34    1    bueno
dér    06a    29    1    bueno
díj    05    14    89    malo
díj    06a    2    101    malo
díj    06b    2    101    malo
díj    07    90    13    bueno
díj    08a    2    101    malo
díj    08b    2    101    malo
egér    06a    66    5    bueno
fonal    05    12    1    bueno
fonal    07    52    4    bueno

期望的输出

Lemma    ---    Score    ---    ---
cserép    06a    55    6    bueno
darázs    05    38    1    bueno
dél    06a    34    1    bueno
dér    06a    29    1    bueno
díj    07    90    13    bueno
egér    06a    66    5    bueno
fonal    07    52    4    malo

我做了什么。但它只在引理重复一次时有效。

BEGIN {
    OFS=FS="\t";
    flag="";
}
{
    id=;

    if (id != flag)
    {
        if (line != "")
        {   
            sub("^;","",line);

            z=split(line,A,";");
            if ((A[3] > A[8]) && (A[8] != ""))
            {
                print A[1]"\t"A[2]"\t"A[3]"\t"A[4]"\t"A[5];
            }
            else if ((A[8] > A[3]) && (A[8] != ""))
            {
                print A[6]"\t"A[7]"\t"A[8]"\t"A[9]"\t"A[10]
            }
            else
            {
                print A[1]"\t"A[2]"\t"A[3]"\t"A[4]"\t"A[5]; 
            }
        }

        delete line;
        flag=id;
    }
    line[]=line[]";"";"";"";";
}
END {

    line=line ";"";"";"";"";"
    sub("^;","",line);

    z=split(line,A,";");
    if ((A[3] > A[8]) && (A[8] != ""))
    {
        print A[1]"\t"A[2]"\t"A[3]"\t"A[4]"\t"A[5];
    }
    else if ((A[8] > A[3]) && (A[8] != ""))
    {
        print A[6]"\t"A[7]"\t"A[8]"\t"A[9]"\t"A[10]
    }
    else
    {
        print A[1]"\t"A[2]"\t"A[3]"\t"A[4]"\t"A[5]
    }

}

使用脚本:

if ( != ) print [=10=]
else 
  {
  score($NR) = 
  print [=10=]
  }

实际上,使用 perl 可能会更好。

使用 gnu awk 测试:

prevLemma !=  {
          if( prevLemma ) {
            print line;
          }
          prevLemma = ;
          prevScore = ;
          line = [=10=];
        }
prevLemma ==  { if( prevScore <  )  {
            prevScore = ;
            line = [=10=];
          }
        }
END         { print line;}
  • 假设是:文件按引理排序
  • 当引理改变时(或者在一开始var为空时)引理、分数和行被保存
  • 当引理改变时(或在 END 中),打印前一个引理的行
  • 当当前行属于同一个引理并且具有更高的分数时,再次保存值

这个不需要按引理对文件进行排序,但是,它会将所有要打印的行保留在内存中(每个引理一个)所以可能不会适用于具有数百万个不同引理的文件。

它也不尊重原始文件的顺序。

最后,假设所有分数都是非负的!

$ cat lemma.awk
BEGIN { FS = OFS = "\t" }
NR == 1 { print }
NR > 1 {
    if ( > score[]) {
        score[] = 
        line[] = [=10=]
    }
}
END { for (lemma in line) print line[lemma] }


$ awk -f lemma.awk lemma.txt
Lemma   --- Score   --- ---
cserép  06a   55    6   bueno
díj     07    90    13  bueno
fonal   07    52    4   bueno
darázs  05    38    1   bueno
egér    06a   66    5   bueno
dél     06a   34    1   bueno
dér     06a   29    1   bueno
$ cat tst.awk
 != prev { printf "%s", maxLine; maxLine=""; max=; prev= }
 >= max  { max=; maxLine=[=10=] ORS }
END  { printf "%s", maxLine }

$ awk -f tst.awk file
Lemma    ---    Score    ---    ---
cserép    06a    55    6    bueno
darázs    05     38    1    bueno
dél    06a    34    1    bueno
dér    06a    29    1    bueno
díj    07    90    13    bueno
egér    06a    66    5    bueno
fonal    07    52    4    bueno