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

时间:2012-10-31 10:54:31

标签: linux shell sed awk

输入如下:

CNNCC
NCNCN
NNNCC
CCNNN
CCCCN

输出应该是这样的:

CNNCC
CCCCN

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

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

有没有人有这方面的想法? shell中的解决方案也可以。

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

awk -FN 'NF<=3'

7 个答案:

答案 0 :(得分:5)

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

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

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

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

声明的意图不是很明显,因此可读性较差。但它具有使char和count参数化的优点,因此可以很容易地重用于不同的设置。

不可否认,这对于大量count来说效率不高。将最大字段数设置为count+1可以克服此性能问题,遗憾的是gawk会忽略-mf选项。

答案 1 :(得分:4)

这可能适合你(GNU sed):

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

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

答案 2 :(得分:2)

使用相同正则表达式的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

答案 3 :(得分:2)

您可以使用gsub来计算:

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

结果:

CNNCC
CCCCN

答案 4 :(得分:2)

grep不爱?

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

更多信息:

-v反转匹配,因此找到不包含3个N的行(如果行超过3个N,则包含3个N)。

egrep相当于使用扩展正则表达式(ERE)的grep -E,此处使用,因此( ){ }不必转义。

答案 5 :(得分:1)

Perl one-liner

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

答案 6 :(得分:0)

这样做:

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