regex - 非常大的文件之间的 Grep 模式匹配太慢了

标签 regex linux grep large-files sequencing

我在这上面花了太多时间,正在寻求建议。我有太大的文件(来自感兴趣的人的 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。有没有人对我如何才能显着加快最后一步有任何建议?

最佳答案

取决于您需要多久运行一次:

  1. 您可以将您的数据转储(您可能希望批量插入并在之后建立索引)到 Postgres(sqlite?)数据库中,在其上建立索引,并享受 40 年的研究成果关系数据库的高效实现,您几乎无需投资。

  2. 您可以通过使用 unix 实用程序“join”来模拟拥有一个关系数据库,但是不会有太多乐趣,因为它不会给您一个索引,但它可能比 ' grep',你可能会遇到物理限制......我从来没有尝试加入两个 18G 文件。

  3. 您可以编写一些 C 代码(将您最喜欢的编译(机器代码)语言放在这里),它将您的字符串(只有四个字母,对吗?)转换为二进制并构建索引(或更多)基于它。由于您的 50 个字符串将仅占用两个 64 位字,因此这可以变得闪电般快速且内存占用量小。

关于regex - 非常大的文件之间的 Grep 模式匹配太慢了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23773669/

相关文章:

python - 在 Python 中解析类似 Stackoverflow 的文本框

python - 在 python 中,如何向正则表达式函数添加特殊情况?

javascript - 用户名不应该是 root 的正则表达式是什么

javascript - 如何创建等于 1,2,3 的正则表达式模式

c - 在 Linux 中通过代码获取域名

linux - 如何在 Linux 中的主文件夹中以另一个用途运行命令 + 使用用户的环境/配置变量?

linux - 自动复制文件

regex - 如何在终端中使用 grep 打印与特定 grep 模式匹配的文件列表?

linux - Grep:在 HEREDOC 中查找文本

linux - 如何判断用户是否登录?