awk:筛选未筛选的非零数

  • 本文关键字:筛选 awk awk
  • 更新时间 :
  • 英文 :


我以前使用awk将一个大部分为零的巨大数据表简化为一个只有有趣行(没有太多零的行(的较小表,如下所示:

awk -F 't' '{count=0} {for(i=2; i<30; i++) if($i==0) count++} {if(count<5) print $0}' BigTable > SmallerTable 

现在我想过滤一个类似的表,以查找大多数"女性"列中具有非零值的行,在大多数"男性"列中查找零值的行。我尝试使用相同的 awk 逻辑,但我的代码返回输入文件的所有行。

#! /usr/bin/awk -f 
FS="t"
{countF=0} {for(i=2; i<7; i++) if($i==0) countF++} 
# count zeros in female columns 2-6
{countM=0} {for(i=7; i<12; i++) if($i==0) countM++} 
# count zeros in male columns 7-12
{if (countF<2 && countM>3) {print $0}}
# if fewer than 2/5 females AND more than 3/5 males are zero, print line

我的输入文件是这样开始的:

NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN F_CR1   F_CR2   F_CR3   F_CR4   F_CR6   M_CR10  M_CR5   M_CR7   M_CR8   M_CR9
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 14727   13526   13318   13862   11040   18975   21411   20079   16285   15611
CCGGTGTGACAACTGTAGTGAACTCAGCTCA 23  32  26  15  28  28  42  29  8   22
AACCAAATCTACAAACAGGAGATGTTGTTCT 107 110 118 106 95  100 121 132 92  90
GAAATAGAACAGGCCTGGAAGCCATGTCAAA 15  15  16  12  11  31  23  19  9   28

我弄乱了打印行中的语法吗?任何建议非常感谢!

FS="t"更改为BEGIN{FS="t"}。现在,该赋值的结果是一个 true 条件,它调用打印每一行的默认操作。

然后将 shell 脚本更改为:

/usr/bin/awk '
BEGIN { FS="t" }
{
# count zeros in female columns
countF=0
for(i=2; i<=6; i++) {
if ($i==0) {
countF++
}
}
# count zeros in male columns
countM=0
for(; i<=NF; i++) {
if ($i==0) {
countM++
}
}
}
# if fewer than 2/5 females AND more than 3/5 males are zero, print line
countF<2 && countM>3
' "$@"

因此,如果您需要将 shell 参数分离为 awk 参数和 awk 变量赋值时,它更尴尬且更容易增强(shebangs 对此没有用(。

还可以考虑缩写它并删除硬编码的男性/女性限制,但从标题行获取它们:

/usr/bin/awk '
BEGIN { FS="t" }
FNR==1 {
for (i=2; i<=NF; i++) {
sub(/_.*/,"",$i)
gender[i] = $i
}
next
}
{
for (i=2; i<=NF; i++) {
count[gender[i]] += ($i==0)
}
}
count["F"]<2 && count["M"]>3
' "$@"

以上内容未经测试,因为您没有提供预期的输出供我们测试。