删除包含 0 次数超过“x”次的行

删除包含 0 次数超过“x”次的行

我有一个很大的逗号分隔文件。我需要过滤掉包含 x 个包含零的列(不包括第一行)的行。为简单起见,假设我想过滤掉包含超过 4 个零的行:

    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2
    gene3,0,0,0,0,6,0,0

将返回:

    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2

过滤掉“gene3”。

这是我尝试过的(尝试使用 ',0' 作为分隔符但失败):

awk -F',0' 'NF<4 {print}' file.csv

答案1

awk -F',0'的三份,0将被视为三份分隔符,给出四个领域总共。因此,如果您使用awk -F',0' 'NF<5 {print}'它,您应该在输出中看到正确的行。

,0还将匹配诸如 之类的字符串213,0123,您可能想也可能不想将其用作零分隔符。

因此,您还可以用作,字段分隔符并计算仅包含一个零的字段:

awk -F, '{z=0; for (i = 1 ; i <= NF ; i++) if ($i == 0) z++} z <= 4' file.csv

答案2

您还可以使用正则表达式和grep.

grep -Ev '(,0(,[^0,]+)*){4,}' file.csv

我在这个文件上测试了它:

gene,v1,v2,v3,v4,v5,v6,v7
gene1,0,1,5,0,0,4,100
gene2,1,0,0,0,5,210,2
gene3,0,0,0,0,6,0,0
gene4,0,0,0,4,6,0,0
gene5,0,1,0,4,6,0,0

有一些假设:

  • 没有以零开头的非零数字,
  • 零数仅包含一个零,
  • 所有数字都是整数。

如果您需要,可以扩展正则表达式来解决此类情况。

答案3

KISS 方法awk

awk -F, '{c = 0; for(i=1; i<=NF; i++) {c += $i == "0" ? 1 : 0}} c <= 3' file.csv
    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2

perl

perl -F, -ne 'print unless (grep { $_ eq "0" } @F) > 3' file.csv
    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2

答案4

如果所有数字都是整数,则使用GNU awk它支持单词边界\<...\>,你可以这样做

gawk 'gsub(/\<0\>/, "0") <5' infile

相关内容