我花了太多时间在这上面,我正在寻找建议。我有太大的文件(来自Illumina测序运行的FASTQ文件,对于那些感兴趣的人)。我需要做的是匹配两个文件之间共同的模式,并将该行和下面的3行打印成两个单独的文件,没有重复(存在于原始文件中)。 Grep这样做很好,但文件大约是18GB,它们之间的匹配非常慢。我需要做的事情的例子如下。
FILEA:
@DLZ38V1_0262:8:1101:1430:2087#ATAGCG/1
NTTTCAGTTAGGGCGTTTGAAAACAGGCACTCCGGCTAGGCTGGTCAAGG
+DLZ38V1_0262:8:1101:1430:2087#ATAGCG/1
BP\cccc^ea^eghffggfhh`bdebgfbffbfae[_ffd_ea[H\_f_c
@DLZ38V1_0262:8:1101:1369:2106#ATAGCG/1
NAGGATTTAAAGCGGCATCTTCGAGATGAAATCAATTTGATGTGATGAGC
+DLZ38V1_0262:8:1101:1369:2106#ATAGCG/1
BP\ccceeggggfiihihhiiiihiiiiiiiiihighiighhiifhhhic
@DLZ38V1_0262:8:2316:21261:100790#ATAGCG/1
TGTTCAAAGCAGGCGTATTGCTCGAATATATTAGCATGGAATAATAGAAT
+DLZ38V1_0262:8:2316:21261:100790#ATAGCG/1
__\^c^ac]ZeaWdPb_e`KbagdefbZb[cebSZIY^cRaacea^[a`c
您可以看到以@
开头的3个唯一标题,后跟3个额外的行
FILEB:
@DLZ38V1_0262:8:1101:1430:2087#ATAGCG/2
GAAATCAATGGATTCCTTGGCCAGCCTAGCCGGAGTGCCTGTTTTCAAAC
+DLZ38V1_0262:8:1101:1430:2087#ATAGCG/2
_[_ceeeefffgfdYdffed]e`gdghfhiiihdgcghigffgfdceffh
@DLZ38V1_0262:8:1101:1369:2106#ATAGCG/2
GCCATTCAGTCCGAATTGAGTACAGTGGGACGATGTTTCAAAGGTCTGGC
+DLZ38V1_0262:8:1101:1369:2106#ATAGCG/2
_aaeeeeegggggiiiiihihiiiihgiigfggiighihhihiighhiii
@DLZ38V1_0262:8:1101:1369:2106#ATAGCG/2
GCCATTCAGTCCGAATTGAGTACAGTGGGACGATGTTTCAAAGGTCTGGC
+DLZ38V1_0262:8:1101:1369:2106#ATAGCG/2
_aaeeeeegggggiiiiihihiiiihgiigfggiighihhihiighhiii
@DLZ38V1_0262:8:1101:1369:2106#ATAGCG/2
GCCATTCAGTCCGAATTGAGTACAGTGGGACGATGTTTCAAAGGTCTGGC
+DLZ38V1_0262:8:1101:1369:2106#ATAGCG/2
_aaeeeeegggggiiiiihihiiiihgiigfggiighihhihiighhiii
这里有4个标题,但只有2个是唯一的,因为其中一个重复3次
我需要两个文件之间没有重复的公共标题加上它们下面的3行。每个文件的顺序相同。
这是我到目前为止所拥有的:
grep -E @DLZ38V1.*/ --only-matching FileA | sort -u -o FileA.sorted
grep -E @DLZ38V1.*/ --only-matching FileB | sort -u -o FileB.sorted
comm -12 FileA.sorted FileB.sorted > combined
结合
@DLZ38V1_0262:8:1101:1369:2106#ATAGCG/
@DLZ38V1_0262:8:1101:1430:2087#ATAGCG/
这只是两个文件之间的公共标题,没有重复。这就是我要的。 现在我需要将这些标题与原始文件匹配,然后抓住它们下面的3行但只有一行。
如果我使用grep,我可以得到我想要的每个文件
while read -r line; do
grep -A3 -m1 -F $line FileA
done < combined > FileA.Final
FileA.Final
@DLZ38V1_0262:8:1101:1369:2106#ATAGCG/1
NAGGATTTAAAGCGGCATCTTCGAGATGAAATCAATTTGATGTGATGAGC
+DLZ38V1_0262:8:1101:1369:2106#ATAGCG/1
BP\ccceeggggfiihihhiiiihiiiiiiiiihighiighhiifhhhic
@DLZ38V1_0262:8:1101:1430:2087#ATAGCG/1
NTTTCAGTTAGGGCGTTTGAAAACAGGCACTCCGGCTAGGCTGGTCAAGG
+DLZ38V1_0262:8:1101:1430:2087#ATAGCG/1
BP\cccc^ea^eghffggfhh`bdebgfbffbfae[_ffd_ea[H\_f_c
重复while循环以生成 FileB.Final
@DLZ38V1_0262:8:1101:1369:2106#ATAGCG/2
GCCATTCAGTCCGAATTGAGTACAGTGGGACGATGTTTCAAAGGTCTGGC
+DLZ38V1_0262:8:1101:1369:2106#ATAGCG/2
_aaeeeeegggggiiiiihihiiiihgiigfggiighihhihiighhiii
@DLZ38V1_0262:8:1101:1430:2087#ATAGCG/2
GAAATCAATGGATTCCTTGGCCAGCCTAGCCGGAGTGCCTGTTTTCAAAC
+DLZ38V1_0262:8:1101:1430:2087#ATAGCG/2
这可行,但FileA和FileB大约为18GB,我的组合文件大约为2GB。有没有人对如何大幅加快最后一步提出任何建议?
答案 0 :(得分:1)
取决于您需要多长时间运行一次:
您可以将您的数据转储(您可能希望随后构建索引的批量插入)到Postgres(sqlite?)数据库中,在其上构建索引,并享受40年研究成果高效实施关系数据库,几乎没有您的投资。
你可以通过使用unix实用程序'join'来模仿关系数据库,但是没有太多的乐趣,因为它不会给你一个索引,但它可能比' grep',你可能遇到了物理限制......我从未试图加入两个18G文件。
你可以写一些C代码(把你最喜欢的编译(到机器代码)语言放在这里),它将你的字符串(只有四个字母,对吧?)转换为二进制并构建一个索引(或更多)基于它。由于你的五十个字符串只占用两个64位字,因此闪存速度快,占用内存小。
答案 1 :(得分:1)
我想我应该发布我想出的修复方法。一旦我获得了组合文件(上面),我使用perl哈希引用将它们读入内存和扫描文件A.文件A中的匹配被哈希并用于扫描文件B.这仍然需要大量内存但工作速度非常快。从grep的20多天到~20分钟。