AWK 根据列总和打印列

AWK 根据列总和打印列

我有一个文件,其中包含矩阵形式的数值。我编写了一个 awk 脚本,该脚本打印标题,然后如果列中的值小于 5 且大于 0,则将 1 添加到列“总和”中。然后,最后打印每列的总和。这部分工作正常:

awk '
  BEGIN {FS=OFS=" "}
  NR==1 {print}
  NR>1  {for (i=1;i<=NF;i++) if ($i < 5 && $i > 0) a[i]+=1}
  END   {for (i=1;i<=NF;i++) printf $a[i]
}' snp_fake2.txt > tmp.txt`

我的目标是,如果该列的总和大于某个值 THRESHOLD,则打印整个列。我尝试在第二个 for 循环后添加一个 if 语句来确定列总和 a[i] 是否 > THRESHOLD,然后打印该列:

awk '
  BEGIN {FS=OFS=" "}
  NR==1 {print}
  NR>1  {for (i=1;i<=NF;i++) if ($i < 5 && $i > 0) a[i]+=1}
  END   {for (i=1;i<=NF;i++) if (a[i] < THRESHOLD) printf $i
}' snp_fake2.txt > tmp.txt`

但是当我运行这个脚本时,它不会输出整个列,而只会输出一个数字。我怎样才能打印整个列而不是仅仅打印单个值?

答案1

AWK 每次处理文件中的一行。它不记忆前几行。END 规则在处理完最后一行后执行。此时 AWK 无法打印列 $i 中的所有条目,因为它只知道列 $i 的一个值:最后一行的值。

您的目标需要对文件进行两次传递:一次计算列总和,第二次打印出整个列(针对相应的列)。为此,您可以编写一个 shell 脚本,调用 awk 来计算总和,然后调用 awk(或其他程序)来打印列。

答案2

如果我理解正确的话,一种方法是使用二维数组。它适用于 GNU awk。

echo -e '1 4 7\n2 5 8\n3 6 9' | awk '
{ for (i=1;i<=NF;i++) {
        field[i][NR]=$i
        if ($i < 5 && $i > 0) {
            a[i]+=1
            }
        }
}
END {
    for (i in a) {
        if (a[i] > 2) {
            for (j in field[i]) print field[i][j]
            }
        }
}'

相关内容