我在这上面花了太多时间,正在寻求建议。我有太大的文件(来自感兴趣的人的 Illumina 测序运行的 FASTQ 文件)。我需要做的是匹配两个文件之间共有的模式,并将该行加上它下面的 3 行打印到两个单独的文件中,不要重复(存在于原始文件中)。 Grep 做得很好,但文件大约 18GB,它们之间的匹配速度慢得离谱。下面是我需要做的示例。
文件A:
@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 个以 @
开头的独特 header ,后跟 3 个附加行
文件B:
@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 次
我需要两个文件之间没有重复的公共(public)标题加上它们下面的 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/
这只是两个文件的共同头文件,没有重复。这就是我要的。 现在我需要将这些 header 与原始文件匹配,并抓取它们下面的 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。有没有人对我如何才能显着加快最后一步有任何建议?
最佳答案
取决于您需要多久运行一次:
您可以将您的数据转储(您可能希望批量插入并在之后建立索引)到 Postgres(sqlite?)数据库中,在其上建立索引,并享受 40 年的研究成果关系数据库的高效实现,您几乎无需投资。
您可以通过使用 unix 实用程序“join”来模拟拥有一个关系数据库,但是不会有太多乐趣,因为它不会给您一个索引,但它可能比 ' grep',你可能会遇到物理限制......我从来没有尝试加入两个 18G 文件。
您可以编写一些 C 代码(将您最喜欢的编译(机器代码)语言放在这里),它将您的字符串(只有四个字母,对吗?)转换为二进制并构建索引(或更多)基于它。由于您的 50 个字符串将仅占用两个 64 位字,因此这可以变得闪电般快速且内存占用量小。
关于regex - 非常大的文件之间的 Grep 模式匹配太慢了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23773669/