删除感兴趣的数量低于截止值的行(Perl)

时间:2017-11-13 19:31:44

标签: perl

我的文件有多个列,其中包含以下格式的文本“number / number:zero,number_of_interest”。示例:“1/1:0,13”。

如果任何列中感兴趣的数量小于20,我需要删除行。 我更喜欢使用egrep而不是读取文件,但不确定如何在单个语句中评估每列感兴趣的数量。

我还删除了包含SVLEN = -1或SVLEN = -2的行,它似乎与egrep一起运行良好:

$cmd2 = `egrep -v 'SVLEN=-1;|SVLEN=-2;' $my_vcf > $my_new_vcf`; print $cmd1;

我尝试过以下但是没有用:

my $cmd2 = `egrep -v 'SVLEN=-1;|SVLEN=-2;|(\,(\d+) < 20)' $my_vcf > $my_new_vcf`; print $cmd2;

谢谢。

1 个答案:

答案 0 :(得分:2)

egrep是用于此目的的错误工具,因为它无法在其正则表达式中进行数学运算。 因为您已经有了Perl脚本,所以最好使用Perl命令来实现目标。

不幸的是,你必须逐行打开并阅读文件才能这样做,但这正是egrep所做的。怎么还能判断这些线?

#!/usr/bin/env perl

use strict;
use warnings;
use List::Util;

sub filter_lines
{
    my $in_filename  = shift;
    my $out_filename = shift;
    open( my $fhin,  '<', $in_filename )  or die "cannot open $in_filename: $!\n";
    open( my $fhout, '>', $out_filename ) or die "cannot open $out_filename: $!\n";
    while ( my $line = <$fhin> ) {

        next if ( $line =~ /SVLEN=-1;|SVLEN=-2;/ );
        if ( my @numbers_of_interest = ( $line =~ m/\d+\/\d+:0,(\d+)/g ) ) {
            next unless List::Util::min(@numbers_of_interest) < 20;
        }

        print $fhout $line;

    }
    close($fhin);
    close($fhout);
}

filter_lines( $my_vcf, $my_new_vcf );

因为我没有确切的输入行,@numbers_of_interest的模式可能有点不准确,需要改进。如果此代码变慢,还有很大的优化空间。