2012-06-20 60 views
2

我有一個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 

該文件有成千上萬行像這樣(也是製表符分隔)。文件的第一列是名稱,第二到第六列是數據。這是第2至第6列的信息很重要。我需要輸出第2至第6列不超過1(零)的所有行。例如,我想輸出看起來像這樣:

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;}' 

但,當我嘗試這個時,它只是給我原始的輸入文件。我不確定什麼是錯,或者我是否採取了正確的方法。任何幫助,將不勝感激。

+0

第一行'out'總是要被GT 4,以便最後一行總是匹配之後。 – starbolin

回答

2

您正在執行的錯誤不是重置每個記錄的輸出變量,而是隻在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}' 
+0

這很好!非常感謝.... – user1352084

0

一種方式perl

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

我假設在每一行名稱不包含數字(具體0),並且它們的長度不超過一位數。另外,如果添加-i標誌,則可以在文件中進行更改。

0
awk ' 
    { 
    nzero=0 
    for (fld = 2; nzero <= 1 && fld <= 6; fld++) { 
     if ($fld == 0) nzero++ 
    } 
    if (nzero <= 1) print 
    } 
' filename 
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 
> 
0

假設列符合特定的格式可能是危險的。下面是使用布爾變量的0,1特性的簡單的解決方案:

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