我在 Linux 中有一张表:
A 0
A 0
A 0
B 0
B 1
B 0
B 1
B 0
我想提取连续出现3次或以上的行。
我的预期输出是:
A 0
实际上,3次或更多只是一个简单的例子。实际情况是我想提取连续出现30次以上的行。
任何想法?
谢谢你!
答案1
uniq -c file | awk '$1 >= 3 { print $2,$3 }'
将uniq -c
输出每一行以及该行连续出现的次数。对于给定的数据,它将产生
3 A 0
1 B 0
1 B 1
1 B 0
1 B 1
1 B 0
awk
如果第一个字段大于或等于 3,脚本将采用此值并输出最后两个字段。
结果将是
A 0
答案2
简单的awk
可以使用如下。
awk '{!s[$0]++} END{for (x in s) if (s[x]>2) print x}' infile
这是打印重复次数超过 2 次>2
但总共重复的行。您可以设置>29
让线条重复 ≥30 次。
您可以使用 @Philippos 指出的以下命令,仅打印重复 ≥3 次的连续行。
awk 'p!=$0{n=0} {p=$0;n++} (n==3)'
说明: 将前一行存储在 中p
,对 中的行进行计数n
,如果一行与前一行不同,则重置计数器。在第 3 次(或第 30次)出现时打印。
或者甚至用简短的方法也可以实现相同的效果:
awk 'p!=$0{n=0;p=$0} ++n==3'
答案3
sed
缺少纯净版!这会做:
sed 'x;G;s/\(.*\)\n\1$/+\1/;/\n/d;h;s/^+\{2\}//;/^+/d' file
2
将by替换29
为连续 30 行。我想知道是否可以以某种方式进行优化。
工作原理:在保留空间中,保留前一行,并+
为每个额外出现的行添加前导。现在,对于每一行,x
交换缓冲区,因此当前行位于保留空间中。附加G
保留空间,因此在模式空间中我们有旧行和新行,由换行符分隔。现在,如果该行出现在换行符之前和之后,我们就有两行相同的行,并且该s
命令将其中一行和换行符替换为+
.如果模式中仍然有换行符,则行不同,我们可以开始新的循环 ( /\n/d
)。否则将修改后的行复制到保留空间以收集+
.最后删除+
所需的行数(减去一行)。如果仍然存在前导+
,则我们收集的行太多或不足,因此d
进行删除。
答案4
与单awk脚本:
awk '{k=$1 FS $2}!a[k] || (NR==n && k==pk){ a[k]++; pk=k; n=NR+1 }
END{ for(i in a) if(a[i] >=3) print i }' file
k=$1 FS $2
- 关键键,第一和第二字段的串联!a[k] || (NR==n && k==pk)
- 检查记录是否第一次出现或与前一条记录同时发生
输出:
A 0