如何通过计算AWK或bash中char的出现来过滤行?

input是这样的:

CNNCC NCNCN NNNCC CCNNN CCCCN 

输出应该是这样的:

 CNNCC CCCCN 

也就是说,如果N出现的次数超过3次,则该行将被过滤掉 ,否则保留。 (在我的工作中,我需要过滤超过500 N的100000行,因此性能可能很重要)

我知道如何在awk中连续N进行过滤,但我不知道如何计算不连续的。

有没有人有这个想法? 在shell解决scheme也可以。

在所有的答案中,我认为这可能是最简单的:

 awk -FN 'NF<=3' 

 awk -FN -vcount=3 'NF<=count' 

或者,对于不支持-v选项的较旧的awk

 awk -FN 'NF<=count' count=3 

该命令使用目标字符作为字段分隔符,允许的最大出现countcount 。 通过比较count的字段count我们可以选择性地打印符合我们标准的行。

声明的意图并不明显,因此不太可读。 但它的优点是具有参数化的字符和count ,因此可以轻松地重复使用不同的设置。

无可否认,这对大量的count来说效率不高。 设置最大字段count+1会克服这个性能问题,不幸的是-mf选项被gawk忽略。

这可能适用于你(GNU sed):

 sed -r '/(.*N){3}/d' file 

要么

 sed 's/N/&/3;T;d' file 

使用相同正则表达式的sed解决方案:

 % sed '/N.*N.*N/d' 

d删除任何地方有三个或更多N字符的每一行。

例:

 % sed '/N.*N.*N/d' <<EOF `heredoc> CNNCC `heredoc> NCNCN `heredoc> NNNCC `heredoc> CCNNN `heredoc> CCCCN `heredoc> EOF CNNCC CCCCN 

你可以使用gsub来计算:

 awk 'gsub(/N/,"N") < 3' file.txt 

结果:

 CNNCC CCCCN 

不爱grep

 count=3 egrep -v "(.*N){$count}" file 

更多信息:

-v反转匹配,所以这找到不包含3个N的行(如果该行具有多于3个N,则包含3个N)。

egrep等同于使用扩展正则表达式(ERE)的grep -E ,这里使用( ){ }不必转义。

Perl单线程

 perl -ne 'print if tr/N/N/ < 3' 

这将做到这一点:

 gawk '/N.*N.*N/ { next; } { print; }'