按列过滤文件

时间:2012-06-20 23:57:24

标签: unix awk

我有一个unix问题。我有一个看起来像这样的文件:

AAAA    0   1   2   2   0

BBBBB   2   2   2   2   2

CCCCC   1   1   0   1   1

DDDD    0   0   0   0   0

EEEEE   2   2   0   2   2

该文件有这么多行(并且也是制表符分隔的)。该文件的第一列是名称,第二列至第6列是数据。第2至第6列中的信息非常重要。我需要输出第2-6列不超过1 0(零)的所有行。例如,我希望输出看起来像这样:

BBBBB   2   2   2   2   2

CCCCC   1   1   0   1   1

EEEEE   2   2   0   2   2

我一直在尝试以尽可能简单的方法执行此操作,并尝试了以下awk命令:

awk 'BEGIN{out!=0;}{if($2!=0)out++;if($3!=0)out++;if($4!=0)out++;if($5!=0)out++;if($6!=0)out++;if (out>=4)print;}'

但是,当我尝试这个时,它只是给了我原始的输入文件。我不确定有什么问题,或者我是否采取了正确的方法。任何帮助将不胜感激。

5 个答案:

答案 0 :(得分:2)

您正在做的错误不是重置每个记录的out变量,而是在BEGIN块中仅初始化一次。 (你也错误地使用“不等于”来初始化它。)

awk '{out = 0; if($2!=0) out++; if($3!=0) out++; if($4!=0) out++; if($5!=0) out++; if($6!=0) out++; if(out>=4) print}'

答案 1 :(得分:0)

使用perl的一种方式:

perl -ne 'print if(tr/0/0/ <= 1)' file.txt

我假设每行上的名字不包含数字(特别是0),并且它们的长度不超过一位数。此外,如果添加-i标志,则可以在文件中进行更改。

答案 2 :(得分:0)

awk '
  {
    nzero=0
    for (fld = 2; nzero <= 1 && fld <= 6; fld++) {
      if ($fld == 0) nzero++
    }
    if (nzero <= 1) print
  }
' filename

答案 3 :(得分:0)

更简单的方法是:

awk '{count=0;for(i=2;i<=NF;i++){if($i~/0/)++count;}if(count <=1)print}' file1

测试如下:

> cat file1
AAAA    0       1       2       2       0
BBBBB   2       2       2       2       2
CCCCC   1       1       0       1       1
DDDD    0       0       0       0       0
EEEEE   2       2       0       2       2
sEEEE   2       0       0       0       2
> awk '{count=0;for(i=2;i<=NF;i++){if($i~/0/)++count;}if(count <=1)print}' file
BBBBB  2 2 2 2 2
CCCCC  1 1 0 1 1
EEEEE  2 2 0 2 2
> 

答案 4 :(得分:0)

假设列符合特定格式可能很危险。下面是使用布尔变量的0,1属性的简单解决方案:

awk '($2==0) + ($3==0) + ($4==0) + ($5==0) + ($6==0) <2' file.txt