AWK打印列中唯一值的最小最大值

AWK to print min max values of unique value in column

我正在尝试使用 awk 执行以下操作:

输入文件:

6:28866209    NA     NA     NA     8.51368e-06   Y  
6:28856689    1   0.007828      1      1.50247e-06   X  
6:28856740    2     0.007828      1      1.50247e-06   Y   
6:28856889    3   7.51E-08      3     1.50247e-06   X

我想:

文件可以有不同的 N 列,但都至少有 1-8 列,这在我的每个文件中都是相同的。

输出:

6:28866209 NA NA NA 8.51368e-06 Y 8.51368e-06 1.50247e-06 
6:28856689 1 0.007828 1 1.50247e-06 X 1.50247e-061.50247e-06 
6:28856740 2 0.007828 1 1.50247e-06 Y 8.51368e-06 1.50247e-06 
6:28856889 3 7.51E-08 3 1.50247e-06 X 1.50247e-06 1.50247e-06

我尝试使用以下 awk 命令执行此操作,但我只取回第 6 列中的第一个值...

awk 'BEGIN{OFS="\t";FS="\t"}{if (a[] == "") a[]=; if (a[] > ) {a[]=}} {if (b[] == "") b[]=; if (b[] < ) {b[]=}} END {if (i=) print [=12=],i,a[i],b[i]}' FILE

我认为最简单的方法是使用文件的双重传递:

awk '(NR==FNR) && !( in min) { min[] = ; max[] = ; next }
     (NR==FNR) { m=min[]; M=max[];
                 min[] = <m ?  : m;
                 max[] = >M ?  : M;
                 next; }
     {print [=10=],min[],max[] }' <file> <file>

您的原始代码存在以下缺陷。 END 语句仅在到达文件末尾时执行。您尝试打印完整文件,但您没有在解析中存储任何行。

对您最初想法的更正是:

awk 'BEGIN{OFS="\t";FS="\t"}
     {if (a[] == "") a[]=;
      if (a[] > ) {a[]=}
     }
     {if (b[] == "") b[]=;
      if (b[] < ) {b[]=}
     }
     { c[NR]=[=11=]; d[NR]= }
     END { for (i=1;i<=NR;i++) print c[i],a[d[i]],b[d[i]] }' FILE

在这里,我将完整的 FILE 存储在数组 c 中,该数组由 line-number NR 索引。我还将索引 </code> 存储在数组 <code>d 中。最后,我遍历存储的所有行并打印预期内容。

  • 这种方法的缺点是您必须将整个文件存储在内存中。
  • 我的建议的缺点是您必须从磁盘读取整个文件两次。
awk 'FNR<NR{=m[];=M[];print;next} (!M[])||>M[]{M[]=}(!m[])||<m[]{m[]=}' file file

有评论

awk '
   # optional format
   BEGIN { OFS=FS="\t"}

   # for second pass (second file read)
   FNR<NR{
      # add a column 7 and 8 with value of min and max correponsing to column 5
      =m[];=M[]
      # print it and reda next line (don't go further in script)
      print;next}

   # this point is only reach by first file read
   # if Max is unknow or value 5  bigger than max
   (!M[])||>M[]{
      # set new max
      M[]=}
   # do the same for min
   (!m[])||<m[]{m[]=}
   # read 2 times the same file (first to find min/max, second to print it)
   ' sample.txt sample.txt