Perl 每个循环都有重复的输出

Perl 每个循环都有重复的输出,perl,Perl,我的代码循环遍历目录中的多个文件,解析每个文件,并将每个文件的解析内容附加到FinalVariantfile.txt 代码可以工作,但会复制每个文件的内容 当我用两个文件运行代码时,输出包含4个文件。有人能解释一下为什么会发生这种情况,以及如何解决这个问题吗 #!/usr/bin/perl -w use strict; #directory structure my $home = "/data/"; my $tsvdirectory

我的代码循环遍历目录中的多个文件,解析每个文件,并将每个文件的解析内容附加到FinalVariantfile.txt

代码可以工作,但会复制每个文件的内容

当我用两个文件运行代码时,输出包含4个文件。有人能解释一下为什么会发生这种情况,以及如何解决这个问题吗

    #!/usr/bin/perl -w

    use strict;

    #directory structure

    my $home         = "/data/";
    my $tsvdirectory = $home . "test_all_runs/" . $ARGV[0];
    my $tsvfiles     = $home . "test_all_runs/" . $ARGV[0] . "/tsv_files.txt";

    my $FinalVariants = $home . "test_all_runs/" . $ARGV[0] . "/FinalVariantfile.txt";

    my @tsvfiles        = ();
    my @currentlines    = ();
    my $currentline     = '';
    my $currentCNVline  = '';
    my @currentCNVlines = ();
    my @HotSpotLines    = ();
    my @CNVLines        = ();

    # command to produce the vcf_files.txt file stored in each individual run
    # directory; the file list includes solely vcf files which have not been
    # previously prepared and/or annotated
    my $cmd = `ls $tsvdirectory/FOCUS*\.tsv > $tsvfiles`;

    # print "$cmd";
    my $cmda = "ls $tsvdirectory/FOCUS*\.tsv > $tsvfiles";

    # print "$cmda";

    # this code opens the vcf_files.txt file and passes each line into an array for
    # indidivudal manipulation
    open( TXT2, "$tsvfiles" );
    while ( <TXT2> ) {
        push( @tsvfiles, $_ );
    }
    close(TXT2);

    foreach ( @tsvfiles ) {
        chop($_);
    }

    # this code then parses each of the files listed by name in the tsvfiles array
    foreach ( @tsvfiles ) {

        my $currenttsvfile = "$_";    # establishes the current file being manipulated

        my $MDLfinaltsvfile = $currenttsvfile;
        $MDLfinaltsvfile =~ s/\.tsv/_prepared\.txt/g;

        # this series of variable calls names the various intermediate or
        # final output files

        my $MDLlinestsvfile = $currenttsvfile;
        $MDLlinestsvfile =~ s/\.tsv/_withCNV\.txt/g;

        my $Variantlinestsvfile = $currenttsvfile;
        $Variantlinestsvfile =~ s/\.tsv/_HotSpot\.txt/g;

        my $MDLtsvfile = $currenttsvfile;
        $MDLtsvfile =~ s/\.tsv/_FilteredAllcolumns\.txt/g;

        my $MDLsampleid = $currenttsvfile;
        $MDLsampleid =~ s/\-oncogene.tsv//g;
        print "The currentVCFis############# " . $currenttsvfile . "\n";

        my @SampleID = ();
        @SampleID = split /\//, $MDLsampleid;
        print "The sampleIDis##############" . $SampleID[4] . "\n";

        my $CNVdata = $currenttsvfile;
        $CNVdata =~ s/\.tsv/_cnv\.txt/g;

        my $FinalCNVdata = $currenttsvfile;
        $FinalCNVdata =~ s/\.tsv/_finalcnv\.txt/g;

        my $cmd2 = `fgrep -v "#" $currenttsvfile > $MDLlinestsvfile`;
        print "$cmd2";    # this code extracts from the current vcf file all of the
                          # lines of data and outputs them into a separate file

        my $cmd5 = `grep -vwE "(CNV|intronic|synonymous|utr_3|utr_5)" 
#removes lines that contain CNV/intronic/synonymous/utr_3/utr_5"

$MDLlinestsvfile > $Variantlinestsvfile`;
        print "$cmd5";

        open( my $fh_in, '<', $Variantlinestsvfile )
                or die "cannot open $Variantlinestsvfile: $!\n"; 
#removes lines that contain 0/0 and ./. genotypes from field 70.

        open( my $fh_out, '>', $MDLtsvfile )
                or die "cannot open $MDLtsvfile: $!\n";

        while ( my $line = <$fh_in> ) {

            # tab/field-based:
            my @fields = split( /\s+/, $line );
            print $fh_out $line unless ( $fields[70] =~ m|([0.])/\1| );
        }
        close($fh_in);
        close($fh_out);

        #open each filtered file with all columns and pushes it into array.
        open( TXT2, "$MDLtsvfile" );
        while (<TXT2>) {
            push( @HotSpotLines, $_ );
        }
        close(TXT2);

        foreach (@HotSpotLines) {
            chop($_);

            my @HotSpotEntries = ();
            my $currentMDLline = $_;
            @HotSpotEntries = split( /\t/, $currentMDLline );

            my $chr        = $HotSpotEntries[9];
            my $position   = $HotSpotEntries[10];
            my $cosmicids  = $HotSpotEntries[21];
            my $refforward = $HotSpotEntries[67];
            my $genotype   = $HotSpotEntries[70];
            my $altforward = $HotSpotEntries[77];
            my $altreverse = $HotSpotEntries[78];
            my $cDNA       = $HotSpotEntries[81];
            my $exon       = $HotSpotEntries[83];
            my $conseq     = $HotSpotEntries[84];
            my $location   = $HotSpotEntries[88];
            my $geneclass  = $HotSpotEntries[92];
            my $aachange   = $HotSpotEntries[98];
            my $transcript = $HotSpotEntries[100];

            $currentline
                    = $SampleID[4] . "\t"
                    . $chr . "\t"
                    . $position . "\t"
                    . $cosmicids . "\t"
                    . $refforward . "\t"
                    . $refreverse . "\t"
                    . $genotype . "\t"
                    . $altforward . "\t"
                    . $altreverse . "\t"
                    . $cDNA . "\t"
                    . $exon . "\t"
                    . $conseq . "\t"
                    . $location . "\t"
                    . $geneclass . "\t"
                    . $aachange . "\t"
                    . $transcript;

            # print "The currentVCFlineis ".$currentline."\n";
            push( @currentlines, $currentline );

        }

        my $i;

        for ( $i = 0; $i < @currentlines; $i += 1 ) {

            my $currentguiline = $currentlines[$i];

            my $cmd5 = `echo "$currentguiline" >> $FinalVariants`;
            print "$cmd5";

            #my $cmd9 = `sed -i '1i$SampleID[4]' $FinalVariants`; print $cmd9;
        }
    }

没有必要启动这么多新的shell子进程来执行这些基本操作。ls、fgrep、grep和echo在Perl中都有等价物,尤其是为每行文本调用echo是将一个文件复制到另一个文件的非常糟糕的方法

我怀疑你的问题是因为线路问题

my$cmd5=`echo$CurrentGuilline>>$FinalVariants`; 它将@currentlines的每个元素追加到文件的末尾。因此,第一次运行程序时,它将包含结果的一个副本,但随后的每次运行都会在文件末尾添加更多数据,并且会不断增长

我不想提供一个黑客来让事情正常工作,但我需要花很多时间才能理解你的程序在所有混乱背后做了什么,并编写一个适当的简明版本。您可以通过添加行来临时修复它

取消链接$FinalVariants或死亡$!; 在foreach@tsvfiles{…}循环之前。这将删除该文件,并确保为程序的每次执行创建新版本

好的,我已经仔细研究了你的代码,我认为这会达到你的目的。由于没有任何数据,甚至没有文件名示例,除了确保它能够编译之外,我无法对它进行测试,因此如果它第一次工作,那将是一个奇迹,但我相信这是获得一致解决方案的最佳机会

请注意,您在自己的代码中使用的$refreverse存在一个问题,但从未声明或定义它,因此您显示的代码不可能产生您所说的问题,因为它在编译过程中消失并显示错误消息

全局符号$refreverse需要显式的包名 我猜它就在指数68的$ref_远期之后

请报告此功能的运行情况

!/usr/bin/perl 严格使用; 使用“全部”警告; 我的$home=/data; my$tsv_directory=$home/test_all_runs/$ARGV[0]; my$final_variants=$tsv_目录/final_variant_file.txt; 打开我的$out\u fh,'>',$final\u变体 或死亡qq{无法打开$final_变量以进行输出:$!}; my@tsv_files=glob$tsv_目录/FOCUS*.tsv; 对于我的$tsv_文件@tsv_文件{ 打印当前VCF为$tsv_文件\n; $tsv|U file=~m |[^/]+-incorgene.tsv$|或die无法提取样本ID; 我的$sample\u id=$1; 打印样本ID为$sample\u ID\n;
打开我的$in_fh,'在ls命令后显示@tsvfiles的内容。这段代码似乎过于复杂,很难理解它似乎在做什么。ls列出了tsv文件的路径,并将其输出到tsv_files.txt中。每个文件只列出一次,因此,我不明白为什么它会在每个文件中循环两次?我所做的就是列出指向感兴趣的文件的路径,循环遍历每个文件,对其进行解析并转储到FinalVariantfile.txt中。我很高兴学习实现同样目的的另一种方法,但是,由于我是一个新手,我尝试说不要使用comlex正则表达式。哪一部分比较混乱?每次运行代码时我都会删除$FinalVariants文件。@user3781528:主要问题m是因为你使用了大量不同的变量和临时文件,所以实际发生的事情很模糊。我确信这是一件非常简单的事情。我不认为问题出在echo上。我尝试了不同的方法,加上它产生了相同的结果。我明天才能测试。谢谢你的建议。我真的很喜欢它的简洁您的代码是,而且运行得很好。经过几次调整后,运行得很好。如果$fields[70]eq'0/0'或$fields[70]eq'/.',我必须将下一个更改为$fields[70]=~m |[0]/\1 |能否建议如何将$sample_id添加为输出的第一列,以及如何从每个.tsv文件中删除头行,以便输出不包含任何头行?Thanks@user3781528:有效吗?我很惊讶!我很抱歉检查$fields[70]:您自己的评论说,从字段70中删除了包含0/0和./.基因型的行,我认为它应该与我所写的其他类似答案相等。如果$fields[70]=~m{\./\.\124; 0/0},我认为应该是下一个因为后面的引用在这里只会混淆,我已经更改了我的答案。很抱歉,我忘了在输出中添加$sample\u id。我也对此进行了更改