【问题标题】:AWK to print min max values of unique value in columnAWK 打印列中唯一值的最小最大值
【发布时间】:2018-09-05 13:49:36
【问题描述】:

我正在尝试使用 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

我想:

  • 为第 6 列中的每个独立值获取第 5 列的最小值和最大值
  • 在文件末尾为每列 5 打印文件中的最小最大值

该文件可以有不同的 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[$6] == "") a[$6]=$5; if (a[$6] > $5) {a[$6]=$5}} {if (b[$6] == "") b[$6]=$5; if (b[$6] < $5) {b[$6]=$5}} END {if (i=$6) print $0,i,a[i],b[i]}' FILE

【问题讨论】:

  • 在END 部分,循环遍历所有数组元素,而不是只选择一个。

标签: awk max min


【解决方案1】:

我相信最简单的做法是使用文件的双重传递:

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

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

对您最初想法的更正是:

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

在这里,我将完整的FILE 存储在数组c 中,该数组由行号NR 索引。我还将索引$6 存储在数组d 中。最后,我循环遍历我存储的所有行并打印预期的内容。

  • 这种方法的缺点是您必须将整个文件存储在内存中。
  • 我的建议的缺点是您必须从磁盘读取完整文件两次。

【讨论】:

  • 太好了。我可以得到您对我尝试处理我的文件的更正(一旦我将i=1;i&lt;=NR;i++} 中的} 调整为))。不幸的是,我无法让您自己的版本正常工作。它为最小值和最大值打印相同的值。感谢您的回答!
  • @LauraC 谢谢。我已经更新了 for 循环的一部分。在我的代码中,第一行缺少!。两者都已更新。
【解决方案2】:
awk 'FNR<NR{$7=m[$6];$8=M[$6];print;next} (!M[$6])||$5>M[$6]{M[$6]=$5}(!m[$6])||$5<m[$6]{m[$6]=$5}' 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
      $7=m[$6];$8=M[$6]
      # 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[$6])||$5>M[$6]{
      # set new max
      M[$6]=$5}
   # do the same for min
   (!m[$6])||$5<m[$6]{m[$6]=$5}
   # read 2 times the same file (first to find min/max, second to print it)
   ' sample.txt sample.txt

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 2015-06-29
    • 1970-01-01
    相关资源
    最近更新 更多