用于隔离行的awk for-loop语法

时间:2015-02-16 04:57:31

标签: for-loop awk

我有一个如下所示的输入文件:

1   Gene1   0.4     0.0009
2   Gene2   0.0003  0.00004
3   Gene3   0.04    0.9
4   Gene4   0.0009  0.00002
5   Gene5   0.8     0.00003

我希望隔离第三($ 3)和第四($ 4)字段小于或等于0.01的行,

我用过:

awk -F"\t" '{ if ($3<=0.01 && $4<=0.01) print $0 }' input

并且它工作正常,但我想使用awk for循环来执行此操作,因为我的实际文件包含十五个这样的字段,并且我不想在上面的代码中键入每个字段。

我试过了:

awk -F"\t" '{ for (i=3; i<=NF; i++) if (i<=0.01) print $0 }' input

但它没有用。我对awk for loop语法不太满意,所以任何帮助都会非常感激。

谢谢。

2 个答案:

答案 0 :(得分:2)

字段i的值为$i。因此,替换:

awk -F"\t" '{ for (i=3; i<=NF; i++) if (i<=0.01) print $0 }' input

使用:

awk -F"\t" '{ for (i=3; i<=NF; i++) if ($i<=0.01) print $0 }' input

然而,上面会打印同一行的多个副本。如果您不想要:

$ awk '{f=0; for (i=3; i<=NF; i++) if ($i<=0.01)f=1;} f' input
1   Gene1   0.4     0.0009
2   Gene2   0.0003  0.00004
4   Gene4   0.0009  0.00002
5   Gene5   0.8     0.00003

如果f非零,则上述命令中的最后awkf简写,用于打印该行。

以上适用or逻辑。您的原始代码使用and逻辑。要使用and逻辑并仅在所有列的值小于或等于0.01时打印,请尝试:

$ awk '{f=1; for (i=3; i<=NF; i++) if ($i>0.01)f=0;} f' input
2   Gene2   0.0003  0.00004
4   Gene4   0.0009  0.00002

或者,这样做相同但只使用<=测试:

$ awk '{f=1; for (i=3; i<=NF; i++) f = f && ($i<=0.01);} f' input
2   Gene2   0.0003  0.00004
4   Gene4   0.0009  0.00002

答案 1 :(得分:0)

如果所有字段都有给定值或其中一个字段或某些其他组合,您是否要打印该行是不明确的,但这样的方法可能会起作用:

awk '
{
    cnt = 0
    for (i=3; i<=NF; i++) {
        cnt += (($i)+0 <= 0.01 ? 1 : 0)
    }
}
cnt { print "at least one true:", $0 }
cnt == (NF-3) { print "all true:", $0 }
' file

我添加了+0以强制进行数字比较,为了清晰起见,我将其设为三元表达式,而不是简单地使用比较结果。