【问题标题】:Grep pattern match between very large files is way too slow非常大的文件之间的 Grep 模式匹配太慢了
【发布时间】:2014-05-21 03:53:31
【问题描述】:

我在这方面花了太多时间,正在寻找建议。我的文件太大(对于感兴趣的人,来自 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 个以 @ 开头的独特标题,后跟 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 次

我需要两个文件之间没有重复的公共标题加上它们下面的 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。有人对我如何显着加快最后一步有什么建议吗?

【问题讨论】:

  • 与其对每个header做一个grep,每次都重新扫描整个文件,为什么不把所有headers放在一个文件里做grep -A3 -m1 -F -f header_list.txt FileA呢?
  • 是的,问题在于 -m1 在第一次命中后会被杀死。

标签: regex linux grep large-files sequencing


【解决方案1】:

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

    1234563关系数据库的高效实现,几乎不需要您进行任何投资。 1234563 grep',你可能会遇到物理限制...我从未尝试加入两个 18G 文件。 1234563基于它。由于您的 50 个字符的字符串只占用两个 64 位的单词,因此这可以实现闪电般的快速和较小的内存占用。

【讨论】:

    【解决方案2】:

    我认为我应该发布我为此提出的修复程序。一旦我获得组合文件(上图),我使用 perl 哈希引用将它们读入内存并扫描文件 A。文件 A 中的匹配被哈希并用于扫描文件 B。这仍然需要大量内存,但运行速度非常快。从使用 grep 的 20 多天到 ~20 分钟。

    【讨论】:

      猜你喜欢
      • 2017-07-30
      • 2013-03-17
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多