grep .fastq中的每四行

时间:2018-11-24 20:35:41

标签: grep fastq

我正在使用bash在Linux机器上工作。

我的问题是,如何使用grep跳过查询文件中的行?

我正在使用一个名为example.fastq的〜16Gb大型.fastq文件,其格式如下。

example.fastq

@SRR6750041.1 1/1
CTGGANAAGTGAAATAATATAAATTTTTCCACTATTGAATAAAAGCAACTTAAATTTTCTAAGTCG
+
AAAAA#EEEEEEEEEEEEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEA<AAEEEEE<6
@SRR6750041.2 2/1
CTATANTATTCTATATTTATTCTAGATAAAAGCATTCTATATTTAGCATATGTCTAGCAAAAAAAA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6
@SRR6750041.3 3/1
ATCCANAATGATGTGTTGCTCTGGAGGTACAGAGATAACGTCAGCTGGAATAGTTTCCCCTCACAG
+
AAAAA#EE6E6EEEEEE6EEEEAEEEEEEEEEEE//EAEEEEEAAEAEEEAE/EAEEA6/EEA<E/
@SRR6750041.4 4/1
ACACCNAATGCTCTGGCCTCTCAAGCACGTGGATTATGCCAGAGAGGCCAGAGCATTCTTCGTACA
+
/AAAA#EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEAE/E/<//AEA/EA//E//
@SRR6750041.5 5/1
CAGCANTTCTCGCTCACCAACTCCAAAGCAAAAGAAGAAGAAAAAGAAGAAAGATAGAGTACGCAG
+
AAAAA#EEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/EEEAEEEAEEE<EE/E

我需要提取包含感兴趣的字符串@SRR6750041.2 @SRR6750041.5的行,该行存储在名为IDarray的bash数组中,以及每次匹配后的3行。以下grep命令允许我执行此操作

for ID in "${IDarray[@]}";
    do
    grep -F -A 3 "$ID " example.fastq 
    done

这将正确输出以下内容。

@SRR6750041.2 2/1
CTATANTATTCTATATTTATTCTAGATAAAAGCATTCTATATTTAGCATATGTCTAGCAAAAAAAA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6
@SRR6750041.5 5/1
CAGCANTTCTCGCTCACCAACTCCAAAGCAAAAGAAGAAGAAAAAGAAGAAAGATAGAGTACGCAG
+
AAAAA#EEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/EEEAEEEAEEE<EE/E

我正在寻找加快此过程的方法...一种方法是通过将搜索限制为以@开头的行或跳过可能不包含匹配{{的行,以减少grep搜索的行数。 1}},例如第2、3、4和6、7、8行等。有没有办法使用grep做到这一点?也欢迎使用其他方法!

1 个答案:

答案 0 :(得分:1)

以下是一些带有示例的想法。出于测试目的,我创建了一个测试用例,例如您的example_mini.fastq的迷你版,其大小为145 MB,IDarray具有999个元素(兴趣)。

您的版本具有这种性能(在用户空间中超过2分钟):

$ time for i in "${arr[@]}"; do grep -A 3 "${i}" example_mini.fastq; done 1> out.txt
real    3m16.310s
user    2m9.645s
sys     0m53.092s

$ md5sum out.txt
8f199a78465f561fff3cbe98ab792262  out.txt

第一次匹配-m 1之后,第一次将grep升级到结束grep,我假设兴趣ID是唯一的。这样可以减少50%的复杂度,并在用户空间中花费大约1分钟的时间:

$ time for i in "${arr[@]}"; do grep -m 1 -A 3 "${i}" example_mini.fastq; done 1> out.txt
real    1m19.325s
user    0m55.844s
sys     0m21.260s

$ md5sum out.txt
8f199a78465f561fff3cbe98ab792262  out.txt

这些解决方案线性依赖于元素数量。在大文件上调用n次grep。

现在让我们仅在AWK中实现一次运行,我将IDarray导出到输入文件中,因此可以一次运行。我将每个ID的大文件加载到关联数组中,然后通过您的ID数组循环搜索1次。这是一般情况,您可以定义正则表达式和打印后的行数。仅通过一次文件+ N次比较就具有复杂性。这提高了2000%:

$ for i in "${arr[@]}"; do echo $i; done > IDarray.txt
$ time awk '
(FNR==NR) && (linesafter-- > 0) { arr[interest]=arr[interest] RS $0; next; }
(FNR==NR) && /^@/ { interest=$1; arr[interest]=$0; linesafter=3; next; }
(FNR!=NR) && arr[$1] { print(arr[$1]); }
' example_mini.fastq IDarray.txt 1> out.txt
real    0m7.044s
user    0m6.628s
sys     0m0.307s

$ md5sum out.txt
8f199a78465f561fff3cbe98ab792262  out.txt

与标题中的一样如果您真的可以确认是否有第四行是感兴趣的ID,则将在其后打印三行。您可以将其简化并再提高20%:

$ for i in "${arr[@]}"; do echo $i; done > IDarray.txt
$ time awk '
(FNR==NR) && (FNR%4==1) { interest=$1; arr[interest]=$0; next; }
(FNR==NR) { arr[interest]=arr[interest] RS $0; next; }
(FNR!=NR) && arr[$1] { print(arr[$1]); }
' example_mini.fastq IDarray.txt 1> out.txt
real    0m5.944s
user    0m5.593s
sys     0m0.242s

$ md5sum out.txt
8f199a78465f561fff3cbe98ab792262  out.txt

在具有999个元素的1.5 GB文件上,搜索时间为:

real    1m4.333s
user    0m59.491s
sys     0m3.460s

因此,根据我对计算机的预测,您的15 GB示例包含10k元素将需要大约16分钟的用户空间来处理。