按长度

时间:2018-04-11 14:19:18

标签: awk fastq

我试图找到一种耗时较少的方法来按顺序长度分割fastq文件,即将一个大的fastq文件拆分成多个只包含相同长度序列的文件。 输入是一个正常的fastq文件(每个序列4行,每个四重奏中第二行的实际序列),序列长度不同:

@HISEQ:28:H8P69ADXX:1:1101:1462:2036 1:N:0:CTTGTA
NCCATAAAGTAGAAAGCACT
+
#00<FFFFFFFFFIIFIIFF
@HISEQ:28:H8P69ADXX:1:1101:1419:2156 1:N:0:CTTGTA
TGGAGAGAAAGGCAGTTCCTGA
+
BBBFFFFFFFFFFIIIIIIIII
@HISEQ:28:H8P69ADXX:1:1101:1378:2223 1:N:0:CTTGTA
TCCTGTACTGAGCTGCCCCGA
+
BBBFFFFFFFFFFIIIIIIII
@HISEQ:28:H8P69ADXX:1:1101:1585:2081 1:N:0:CTTGTA
AAACCGTTACCATTACTGAGT
+
BBBFFFFFFFFFFIIIIFIII

现在我使用awk过滤掉特定长度或特定范围内的序列:

awk 'BEGIN {OFS = "\n"} {header = $0 ; getline seq ; getline qheader ; getline qseq ; if (length(seq) == 22) {print header, seq, qheader, qseq}}'

如果我想为每个序列长度都有一个输出文件,我使用for循环管理:

for i in {16..33};
awk -v var=$i 'BEGIN {OFS = "\n"} {header = $0 ; getline seq ; getline qheader ; getline qseq ; if (length(seq) == var) {print header, seq, qheader, qseq}}'
done

问题是,虽然它工作正常但是相当耗时,因为我猜测每个长度分别检查整个文件。另外,我需要事先检查最长和最短的序列。

任何人都可以帮助我找到比我的循环更有效的解决方案吗?如果可能的话,我不需要指定范围,而是检查最小和最大长度的解决方案并自动拆分。我想在awk中这样做,但我会为所有事情敞开心扉。 谢谢 本尼迪克特

1 个答案:

答案 0 :(得分:3)

这样的事情?

$ awk        '{rec=rec sep $0; sep=ORS} 
       !(NR%4){print rec > fn; rec=sep=""} 
       NR%4==2{fn = length($0)".seq"}' file

将生成包含内容

的这3个文件
==> 20.seq <==
@HISEQ:28:H8P69ADXX:1:1101:1462:2036 1:N:0:CTTGTA
NCCATAAAGTAGAAAGCACT
+
#00<FFFFFFFFFIIFIIFF

==> 21.seq <==
@HISEQ:28:H8P69ADXX:1:1101:1378:2223 1:N:0:CTTGTA
TCCTGTACTGAGCTGCCCCGA
+
BBBFFFFFFFFFFIIIIIIII
@HISEQ:28:H8P69ADXX:1:1101:1585:2081 1:N:0:CTTGTA
AAACCGTTACCATTACTGAGT
+
BBBFFFFFFFFFFIIIIFIII

==> 22.seq <==
@HISEQ:28:H8P69ADXX:1:1101:1419:2156 1:N:0:CTTGTA
TGGAGAGAAAGGCAGTTCCTGA
+
BBBFFFFFFFFFFIIIIIIIII

因为会有少数这些输出文件,所以不需要显式关闭它们。

<强>解释

  

{rec=rec sep $0; sep=ORS}在行之间逐行构建记录行,使用分隔符的延迟初始化,我们可以消除悬空的第一个分隔符。

     如果行号是4的倍数,则

!(NR%4)

     

{print rec > fn; rec=sep=""}将记录打印到文件并重置记录和分隔符

     

NR%4==2如果行号是2的4。

     

{fn = length($0)".seq"}设置文件名