我有一个如下所示的文件:
chr1 3000823 3000829 1
chr1 3001003 3001009 1
chr1 3001014 3001020 1
chr1 3001273 3001279 2
chr1 3001625 3001631 3
chr1 3003222 3003228 4
chr1 3003335 3003341 4
chr1 3003375 3003381 4
chr1 3003578 3003584 4
chr1 3003636 3003642 4
chr1 3003717 3003723 4
chr1 3003881 3003887 4
chr1 3003894 3003900 4
chr1 3004526 3004532 5
chr1 3005994 3006000 6
chr1 3006183 3006189 6
chr1 3006412 3006418 7
chr1 3006778 3006784 8
chr1 3006877 3006883 8
chr1 3007166 3007172 9
chr1 3007426 3007432 10
chr1 3007528 3007534 10
chr1 3007576 3007582 10
我只想获取第四列中包含特定次数任意数字的行。
假设我想在第 4 列中获取具有 3 倍相同数字的行,因此输出将是:
chr1 3000823 3000829 1
chr1 3001003 3001009 1
chr1 3001014 3001020 1
chr1 3007426 3007432 10
chr1 3007528 3007534 10
chr1 3007576 3007582 10
..这是因为这些行的数字 1 和 10 在第 4 列中出现了 3 次
任何想法将不胜感激。谢谢!
答案1
解决方案awk
:
awk 'FNR==NR{c[$4]++;next;} c[$4]==3' file.dat file.dat
输出:
chr1 3000823 3000829 1
chr1 3001003 3001009 1
chr1 3001014 3001020 1
chr1 3007426 3007432 10
chr1 3007528 3007534 10
chr1 3007576 3007582 10
解释:
FNR==NR
:当记录数等于文件中的记录数时,此测试为真。这仅适用于第一个文件,因为第二个文件NR
将等于 file1 + FNR 的行数。c[$4]++
:将数组元素索引增加$4
。我用它作为计数器。next
:跳到下一条记录,不做任何其他事情。c[$4]==3
:这只发生在第二个文件的记录上。如果此测试成功,则将打印该行,因为打印是awk
.
这段代码的缺点是要读取文件两次,但在我看来,这是完成这项工作的一种干净且易于理解的方法。
答案2
{
i = int(count[$4])
arr[$4,i] = $0
count[$4]++
}
END {
for (i in count) {
if (count[i]== n) {
for (j=0; j<n; j++) {
printf("%s\n", arr[i,j])
}
}
}
}
sample run --
awk -v n=3 -f 1.awk 1.dat
chr1 3007426 3007432 10
chr1 3007528 3007534 10
chr1 3007576 3007582 10
chr1 3000823 3000829 1
chr1 3001003 3001009 1
chr1 3001014 3001020 1
awk -v n=8 -f 1.awk 1.dat
chr1 3003222 3003228 4
chr1 3003335 3003341 4
chr1 3003375 3003381 4
chr1 3003578 3003584 4
chr1 3003636 3003642 4
chr1 3003717 3003723 4
chr1 3003881 3003887 4