删除具有低质量碱基检出的读物

时间:2019-04-01 16:47:39

标签: linux perl awk fastq

我有一个fastq格式https://en.wikipedia.org/wiki/FASTQ_format的序列数据文件,其中第一行是序列ID,第二行是序列[ACGT],第三行是“ +”,第四行是质量值。

@M01610:118:000000000-D49F3:1:1101:14523:2546 1:N:0:CTTGTA
GTACACCTTCATGAAGAACTCCATCACCTTCATCTCCAGGATGCGGTCCTGGGTGCTGTTCCTGGCGATCTCGATCAGCTCGATGTACTCGTGGGGCACGTACTTCAGCTTGTGCCGCAGCTCGGACTTCTTCTCCTCCAGCTCGCTCTTCACCAGCTGGGATCCCCGCAGGTGTATCTTGGTATGCTTGTTCAGGTTGGAGCGGTGGGCAAATTTCCTCCCACAAATGTCACAGGCAAAAGGCTTCTC
+
CCCCCFFFFFFFGGGGGGGGGGHHHHHHHHHHHHHHGHHHGHHHGGGGGHHHGFGGHHHHHHHFHHGGGGHHHGGHGHHHHGGHHHHHHHGHGGGGGGGGHHHHHHHGHHHHHHHHGGGGGGHGGGGGHHHHHHHHHHHHHHHHGGGHHHHHHHHFHHHGEHFGHHGGGGGGGHGHFHHHHHFFHHGGGGGGGGGGFFF?FGGGGFGGGFFFFFFFFFFFFEFFF?FFFFFFEFFEFFFFBFFFFFBFF
@M01610:118:000000000-D49F3:1:1101:9569:5713 1:N:0:CTTGTA
CAAGGAAGGCACGGGGGAGGGGCAAACAACAGATGGCTGGCAACTAGAAGGCACAGGCTAGCCAGGCGGGGAGGCGGCCCAAAGGGAGATCCGACTCGTCGGAGGCCGAAAGCGAAGACGCGGGAGAGGCCGCAGAACCGGCAGAAGGCCTCGGGAAGGGAGGTCCGCTGGATTGAGAGCCGAAGGGACGTAGCAGAAGGACGTCCCGCGCAGGATCCAGTTGGCAACACAGGCGAGCAGCCAAGG
+
CDCCDFFFDCFFGGGGGGGGGGGGGHHHHHHHHHHHHHGGGHHHHHHHHHHHHHHHHGHHHHHHHGHGGGGGCGGFGGGGDHHHHGHGGHHHHGGGGFHGFGAGGGGGAAGFFDBF-DFFF>DF;DFAFDF=CA>CFBE>FFCFEFBFFF0FDDFAFFFFEDC.BFFFDBF.FFEBFFFEFAAC=FFE?>AEFEBFBFFFFFFDFFFFC>-9>=ABFFFFBFFFFFFFFFEFFFCFFA9BBEAFEF

我要删除第4行中的任何字符与任何符号?@ABCDEFGHIJK都不匹配的所有条目

以上示例的输出为

@M01610:118:000000000-D49F3:1:1101:14523:2546 1:N:0:CTTGTA
GTACACCTTCATGAAGAACTCCATCACCTTCATCTCCAGGATGCGGTCCTGGGTGCTGTTCCTGGCGATCTCGATCAGCTCGATGTACTCGTGGGGCACGTACTTCAGCTTGTGCCGCAGCTCGGACTTCTTCTCCTCCAGCTCGCTCTTCACCAGCTGGGATCCCCGCAGGTGTATCTTGGTATGCTTGTTCAGGTTGGAGCGGTGGGCAAATTTCCTCCCACAAATGTCACAGGCAAAAGGCTTCTC
+
CCCCCFFFFFFFGGGGGGGGGGHHHHHHHHHHHHHHGHHHGHHHGGGGGHHHGFGGHHHHHHHFHHGGGGHHHGGHGHHHHGGHHHHHHHGHGGGGGGGGHHHHHHHGHHHHHHHHGGGGGGHGGGGGHHHHHHHHHHHHHHHHGGGHHHHHHHHFHHHGEHFGHHGGGGGGGHGHFHHHHHFFHHGGGGGGGGGGFFF?FGGGGFGGGFFFFFFFFFFFFEFFF?FFFFFFEFFEFFFFBFFFFFBFF

此处,seq ID @M01610:118:000000000-D49F3:1:1101:9569:5713 1:N:0:CTTGTA的第四行包含?@ABCDEFGHIJK以外的符号,因此将其删除。

seq ID的第二行和第四行的长度相同,但是不同的seqID在200至250之间变化。

一个单元由4行组成(seq ID,sequence,+ sing,sequence的质量)。我要删除所有序列(第二行)中每个字符的序列质量(第四行)与模式?@ABCDEFGHIJK的任何一个字符都匹配的单元。我已经尝试过此代码,但仍在进行

cat file.fq | awk 'NR%4==0' | xargs -n1 awk '{ for(i=0; ++i <= length($0);) printf "%s\n" }' 

我将不胜感激。

4 个答案:

答案 0 :(得分:3)

为缓冲区中的每个单元收集行;在每个新的标题行处处理上一个单元(检查缓冲区的最后一行,是否打印)并清空缓冲区

use warnings;
use strict;
use feature 'say';

sub process_unit {
    my ($rbuf) = @_;
    if (not $rbuf->[-1] =~ tr/?@ABCDEFGHIJK//dr ) { #/ no extra chars
        say for @$rbuf;
    }
}

my $file = shift // die "Usage: $0 filename\n";   #/    
open my $fh, '<', $file or die "Can't open $file: $!";

my @buf;
while (<$fh>) {
    chomp;
    if (/^\@/ and @buf) {
        process_unit(\@buf);
        @buf = (); 
    }   

    push @buf, $_; 
}
process_unit(\@buf);  # the last unit

使用tr说明对缓冲区中最后一行的检查 (记录在in perlop中):

tr/..//dr从其目标字符串中删除所有列出的字符,并返回修改后的字符串,同时保持原始字符串不变(由于“非破坏性” /r修饰符)。因此,如果删除允许的字符后还有剩余,我们将丢弃该单元(不打印它)。


关于tr和效率选择的说明

可以将正则表达式及其匹配运算符与否定的字符类一起使用

if (not /[^?\@ABCDEFGHIJK]/) { ... }

代替音译运算符tr(不是 正则表达式)。

但是,即使在最适合匹配运算符的情况下,我也将tr方法的基准速度提高了25%。在所有其他情况下,tr至少比regex的匹配效果好2-4倍。

match运算符的“最佳情况”是字符串中的不可接受字符位于字符串的第一个位置时,它立即匹配并且不扫描字符串的其余部分。至少可以说这是不现实的。 相反,从统计上讲,许多(大多数?)字符串都不会包含这些字符,并且match运算符的情况最糟,即扫描整个字符串。 (但是,成本中最大的一部分可能还是正则表达式引擎的启动。)

答案 1 :(得分:3)

$ awk '{unit=unit $0 ORS} NR%4==0{if (/^[?@ABCDEFGHIJK]+$/) printf "%s", unit; unit=""}' file
@M01610:118:000000000-D49F3:1:1101:14523:2546 1:N:0:CTTGTA
GTACACCTTCATGAAGAACTCCATCACCTTCATCTCCAGGATGCGGTCCTGGGTGCTGTTCCTGGCGATCTCGATCAGCTCGATGTACTCGTGGGGCACGTACTTCAGCTTGTGCCGCAGCTCGGACTTCTTCTCCTCCAGCTCGCTCTTCACCAGCTGGGATCCCCGCAGGTGTATCTTGGTATGCTTGTTCAGGTTGGAGCGGTGGGCAAATTTCCTCCCACAAATGTCACAGGCAAAAGGCTTCTC
+
CCCCCFFFFFFFGGGGGGGGGGHHHHHHHHHHHHHHGHHHGHHHGGGGGHHHGFGGHHHHHHHFHHGGGGHHHGGHGHHHHGGHHHHHHHGHGGGGGGGGHHHHHHHGHHHHHHHHGGGGGGHGGGGGHHHHHHHHHHHHHHHHGGGHHHHHHHHFHHHGEHFGHHGGGGGGGHGHFHHHHHFFHHGGGGGGGGGGFFF?FGGGGFGGGFFFFFFFFFFFFEFFF?FFFFFFEFFEFFFFBFFFFFBFF

答案 2 :(得分:2)

这是一种利用(1)修改后的输入记录保护程序和(2)用tr///c c 恭维开关修改的音译运算符的方法。

(我在脚本顶部模拟了文件)

#!/usr/bin/perl
use strict;
use warnings;

my $file =<<'EOF';
@M01610:118:000000000-D49F3:1:1101:14523:2546 1:N:0:CTTGTA
GTACACCTTCATGAAGAACTCCATCACCTTCATCTCCAGGATGCGGTCCTGGGTGCTGTTCCTGGCGATCTCGATCAGCTCGATGTACTCGTGGGGCACGTACTTCAGCTTGTGCCGCAGCTCGGACTTCTTCTCCTCCAGCTCGCTCTTCACCAGCTGGGATCCCCGCAGGTGTATCTTGGTATGCTTGTTCAGGTTGGAGCGGTGGGCAAATTTCCTCCCACAAATGTCACAGGCAAAAGGCTTCTC
+
CCCCCFFFFFFFGGGGGGGGGGHHHHHHHHHHHHHHGHHHGHHHGGGGGHHHGFGGHHHHHHHFHHGGGGHHHGGHGHHHHGGHHHHHHHGHGGGGGGGGHHHHHHHGHHHHHHHHGGGGGGHGGGGGHHHHHHHHHHHHHHHHGGGHHHHHHHHFHHHGEHFGHHGGGGGGGHGHFHHHHHFFHHGGGGGGGGGGFFF?FGGGGFGGGFFFFFFFFFFFFEFFF?FFFFFFEFFEFFFFBFFFFFBFF
@M01610:118:000000000-D49F3:1:1101:9569:5713 1:N:0:CTTGTA
CAAGGAAGGCACGGGGGAGGGGCAAACAACAGATGGCTGGCAACTAGAAGGCACAGGCTAGCCAGGCGGGGAGGCGGCCCAAAGGGAGATCCGACTCGTCGGAGGCCGAAAGCGAAGACGCGGGAGAGGCCGCAGAACCGGCAGAAGGCCTCGGGAAGGGAGGTCCGCTGGATTGAGAGCCGAAGGGACGTAGCAGAAGGACGTCCCGCGCAGGATCCAGTTGGCAACACAGGCGAGCAGCCAAGG
+
CDCCDFFFDCFFGGGGGGGGGGGGGHHHHHHHHHHHHHGGGHHHHHHHHHHHHHHHHGHHHHHHHGHGGGGGCGGFGGGGDHHHHGHGGHHHHGGGGFHGFGAGGGGGAAGFFDBF-DFFF>DF;DFAFDF=CA>CFBE>FFCFEFBFFF0FDDFAFFFFEDC.BFFFDBF.FFEBFFFEFAAC=FFE?>AEFEBFBFFFFFFDFFFFC>-9>=ABFFFFBFFFFFFFFFEFFFCFFA9BBEAFEF
EOF

{
    local $/ = '@';     # set input record separator in this scope to '@'
    open my $fh, '<', \$file;
    <$fh>;              # discard first read (will only contain '@')

    while (<$fh>) {
        chomp;
        my ($test) = /\+\n^(.+)$/m; # grab the fourth line

        # print record (with leading @ prepended back to beginning of record)
        #  unless there  are unwanted characters
        print "\@$_" unless $test =~ tr/?@ABCDEFGHIJK//c;
    }   
}

答案 3 :(得分:0)

如果您的数据位于“ d”文件中,则可能会检出:

 perl -ne 'if (/@M0\w*:\d\d\d:/) {$s=$_;$s.=<> for 1..2;$r=<>; if ($r =~ /[^\s?A-K]/) {next} else {$s.=$r;print $s}}' d