Unix 删除具有特定图案的线条

Unix 删除具有特定图案的线条,unix,awk,lines,text-processing,Unix,Awk,Lines,Text Processing,我有一个特定格式的文件: T 11722 A 330:0:0:0:0:0 315:0:0:0:0:0 T 11723 B 0:330:0:0:0:0 0:316:0:0:0:0 T 11725 C 0:327:0:0:0:0 0:314:0:0:0:0 T 11726 D 330:0:0:0:0:0 314:0:0:0:0:0 T 11727 E 0:6:0:323:0:0 0:6:0:309:0:0 T 117

我有一个特定格式的文件:

T   11722   A   330:0:0:0:0:0   315:0:0:0:0:0
T   11723   B   0:330:0:0:0:0   0:316:0:0:0:0
T   11725   C   0:327:0:0:0:0   0:314:0:0:0:0
T   11726   D   330:0:0:0:0:0   314:0:0:0:0:0
T   11727   E   0:6:0:323:0:0   0:6:0:309:0:0
T   11728   F   0:0:0:328:0:0   0:1:0:314:0:0
T   11729   G   0:325:0:0:0:0   0:315:0:0:0:0
T   11722   A   330:0:0:0:0:0   315:0:0:0:0:0
我想删除第4列和第5列中没有两个值的任何行

例如,如果一行具有特定格式:

T   11722   A   330:0:0:0:0:0   315:0:0:0:0:0
T   11723   B   0:330:0:0:0:0   0:316:0:0:0:0
T   11725   C   0:327:0:0:0:0   0:314:0:0:0:0
T   11726   D   330:0:0:0:0:0   314:0:0:0:0:0
T   11727   E   0:6:0:323:0:0   0:6:0:309:0:0
T   11728   F   0:0:0:328:0:0   0:1:0:314:0:0
T   11729   G   0:325:0:0:0:0   0:315:0:0:0:0
T   11722   A   330:0:0:0:0:0   315:0:0:0:0:0
移除它

如果具有以下格式(第4列和第5列中每列两个值):

留着吧

因此,预期结果应该是:

T   11727   E   0:6:0:323:0:0   0:6:0:309:0:0
T   11728   F   0:0:0:328:0:0   0:1:0:314:0:0
我不知道如何在unix下设置一些东西,但我猜应该有一个简单的方法。任何帮助都将不胜感激

非常感谢awk解决方案:

awk 'function get_count(s, c, len) { 
         len=split(s,a,":"); while(len--) if(a[len]){ c++ } 
         return c 
     } BEGIN { FS=OFS="\t" }get_count($4) > 1 || get_count($5) > 1' file

  • 函数get_count(s,c,len){…}
    函数返回给定字符串中非零值的计数

  • split(s,a,“:”
    -通过分隔符将字符串
    s
    拆分为数组
    a

  • P> >(LeN-)(A[Le]){C++ +} /COD>累积非零计数

输出:

T   11727   E   0:6:0:323:0:0   0:6:0:309:0:0
T   11728   F   0:0:0:328:0:0   0:1:0:314:0:0

您是否只是想打印$4或$5中有2个或更多非零值的行?那就是:

$ awk 'gsub(/[1-9][0-9]*/,"&",$4)>1 || gsub(/[1-9][0-9]*/,"&",$5)>1' file
T 11727 E 0:6:0:323:0:0 0:6:0:309:0:0
T 11728 F 0:0:0:328:0:0 0:1:0:314:0:0

如何处理F行?根据您的逻辑,预期结果将只包含2行,对吗?@Pieter21,F行在第5列中有两个值,所以我想保留它。@RomanPerekhrest,是的,预期结果将只包含2行。我将用预期的结果更新我的问题。@AP38,我还将在第4列或第5列中指出每列两个值,但不是。在Awk函数中生成“局部”变量有一个技巧:将它们命名为函数的参数(但在调用函数时不需要为它们提供值):
函数get\u count(s,c,len){ … }
。当使用单个参数调用函数时,这些变量被初始化为零/空,并且与函数外部具有相同名称的变量分开。在
gsub
表达式之后,它应该成为,例如,
0:&:0:&:0:0
,以及
>1
在这里的含义是什么?您能帮助解释一下吗?
&
是一个反向引用,表示“与regexp匹配的整个字符串”,就像在sed中一样。
>1
表示
大于1
。所以gsub()将自行替换每个匹配字符串,并返回其执行该操作的次数计数,如果计数大于1,则至少会找到2个非零数字。好的,太棒了。gsub中的
&
用于保持匹配模式。并使用gsub的返回值来区分替换数。感谢您的解释非常感谢@EdMorton!这真是太好了!@EdMorton,我唯一要添加到这个方法中的是
OFS='\t'