美文网首页
2019-08-08 perl 子程序 重复打开文件句柄

2019-08-08 perl 子程序 重复打开文件句柄

作者: xiaoguolaile | 来源:发表于2019-08-08 14:48 被阅读0次
    写了一个perl脚本,调用了两个子程序,这两个子程序中分别都要遍历一个文件。
    刚开始将子程序需要重复遍历的文件句柄没有放在子程序中重复打开,而是放在了脚本开始;如下:
    open DMR,"$ARGV[0]";
    open MATC,"$ARGV[1]";
    open MATS,"$ARGV[2]";
    
    while(<DMR>){
          ...
         @a=&sub1(a,b,c);
         @b=&sub2(a,b,c);
         ...
    }
    
    sub sub1{
        ...
    while(<MATC>){...}
    return ...
    }
    sub sub2{
        ...
    while(<MATC>){...}
    return ...
    }
    close DMR;
    close MATC;
    close MATS;
    每次脚本运行的结果都显示子程序调用了一次,第二次调用的时候都无法返回想要的值;
    折腾了一上午,各种测试,各种修改,各种百度,没有找到原因;
    最后测试到子程序才恍然大悟,第一次调用子程序后,文件句柄MATC和MATS已经被遍历完了,无法再次遍历,导致
    子程序调用了一次后就无法再次返回有效值了,哭死....,菜鸟级选手,发现的太晚了。
    解决办法就是将文件句柄放在子程序中进行遍历;
    但是作为新手,每次读取一行文件,子程序都要重复打开文件句柄然后关闭,然后下次继续打开关闭,太不效率了;
    
    后来又发现了seek()函数
    seek()函数是通过文件句柄来移动文件读写指针的方式来读取或写入文件的,以字节为单位进行读取和写入:
    
    seek FILEHANDLE, POSITION, WHENCE
    
    参数说明:
    
        FILEHANDLE:文件句柄,用于存放一个文件唯一标识符。
        POSITION:表示文件句柄(读写位置指针)要移动的字节数。
        WHENCE:表示文件句柄(读写位置指针)开始移动时的起始位置,可以取的值为0、1、2;分别表示文件开头、当前位置和文件尾。
    
    在我们的子程序中遍历文件,我们可以用seek(FILEHANDLE, 0, 0)来代替不断的open 和close 文件句柄了。
    这样在脚本开头open,脚本结束close就可以了。
    
    原始文件(<DMR>)
    $zxg head ./DMR/Stress0_VS_Control0.DMR.txt 
    Chr     Start             End     Length  N_C     Stress0  Control0 Diff    AreaStat     Direction
    chr1    3998120         3998220    100     8       0.8635  0.5784  0.2851  55.3665        Hyper
    chr1    6916517         6917222    705     69      0.9187  0.5976  0.3211  695.3536       Hyper
    chr1    9454505         9454633    128     8       0.5281  0.2002  0.3280  52.8468        Hyper
    chr1    10970705        10970870  165     26      0.8999  0.5681  0.3317  307.8769        Hyper
    chr1    15955916        15956232  316     28      0.9360  0.6386  0.2973  267.6975        Hyper
    chr1    17793102        17793290  188     9       0.8104  0.4703  0.3402  78.3708          Hyper
    chr1    19440293        19441256   963     42      0.9334  0.4415  0.4919  618.3510        Hyper
    chr1    20705333        20705755   422     38      0.9415  0.2969  0.6446  886.2865        Hyper
    chr1    20955313        20955493   180     15      0.3614  0.6616  -0.3002 -110.5831       Hypo
    
    
    control组的matrix 9个样品
    $zxg head matrix_control.txt 
    chr     pos              C03               C04              C05          C112           C13                C19           C210            C214               C21
    chr1    100000060       1.000,13,0      0.909,10,1      0.909,10,1      0.889,8,1       1.000,17,0      0.333,1,2       1.000,13,0      0.929,13,1      1.000,8,0
    chr1    100000061       0.947,18,1      0.786,11,3      0.917,11,1      0.923,12,1      0.944,17,1      0.812,13,3      0.905,19,2      0.947,18,1      1.000,17,0
    chr1    100000094       0.750,9,3       0.833,10,2      0.917,11,1      0.875,7,1       0.933,14,1      0.800,4,1       0.900,9,1       0.857,12,2      1.000,10,0
    chr1    100000095       0.952,20,1      0.765,13,4      0.786,11,3      0.765,13,4      1.000,16,0      0.882,15,2      0.929,26,2      0.900,18,2      0.765,13,4
    chr1    100000185       0.957,22,1      1.000,16,0      1.000,17,0      1.000,13,0      0.846,11,2      1.000,10,0      1.000,14,0      1.000,15,0      1.000,12,0
    chr1    100000186       1.000,24,0      1.000,23,0      1.000,21,0      1.000,21,0      1.000,24,0      0.944,17,1      0.920,23,2      1.000,12,0      0.938,15,1
    chr1    100000190       1.000,23,0      0.938,15,1      0.882,15,2      1.000,13,0      0.917,11,1      0.917,11,1      0.929,13,1      1.000,12,0      1.000,12,0
    chr1    100000191       1.000,24,0      1.000,21,0      0.952,20,1      1.000,21,0      1.000,25,0      0.941,16,1      1.000,24,0      0.917,11,1      1.000,17,0
    chr1    100000477       1.000,16,0      1.000,10,0      0.900,9,1       1.000,10,0      0.864,19,3      1.000,18,0      0.933,14,1      1.000,10,0      1.000,14,0
    
    
    stressl组的matrix 9个样品
    $zxg head matrix_stress.txt 
    chr     pos     H202    H203    H209    H2110   H2111   H217    H224    H228    H229
    chr1    100000060       1.000,15,0      0.909,10,1      1.000,9,0       0.917,11,1      1.000,5,0       0.833,5,1       0.875,14,2      1.000,5,0       0.727,8,3
    chr1    100000061       0.818,18,4      0.826,19,4      0.931,27,2      0.700,7,3       0.846,11,2      0.882,15,2      0.917,11,1      1.000,15,0      1.000,12,0
    chr1    100000094       0.778,14,4      1.000,11,0      0.800,8,2       0.909,10,1      1.000,5,0       1.000,7,0       0.941,16,1      1.000,8,0       0.900,9,1
    chr1    100000095       0.875,21,3      0.857,18,3      0.939,31,2      0.727,8,3       1.000,10,0      0.842,16,3      0.929,13,1      0.875,14,2      1.000,10,0
    chr1    100000185       0.955,21,1      0.909,10,1      1.000,12,0      0.889,8,1       1.000,9,0       1.000,7,0       0.867,13,2      1.000,9,0       0.875,7,1
    chr1    100000186       1.000,29,0      0.960,24,1      1.000,33,0      0.818,9,2       1.000,10,0      1.000,12,0      0.938,15,1      1.000,17,0      0.909,10,1
    chr1    100000190       1.000,21,0      0.917,11,1      1.000,12,0      0.900,9,1       1.000,9,0       1.000,8,0       1.000,14,0      1.000,9,0       0.875,7,1
    chr1    100000191       1.000,29,0      1.000,25,0      0.970,32,1      0.917,11,1      1.000,10,0      1.000,12,0      1.000,16,0      0.941,16,1      1.000,10,0
    chr1    100000477       1.000,12,0      1.000,19,0      1.000,19,0      1.000,18,0      1.000,10,0      0.941,16,1      1.000,15,0      1.000,12,0      0.909,10,1
    
    
    
    程序前边的变量声明
    #! /usr/bin/perl -w
    use strict;
    
    my $head;
    my %hash_c;
    my %hash_s;
    
    open DMR,"$ARGV[0]";
    $head=<DMR>;
    chomp $head;
    
    主程序
    
    while (<DMR>){
    chomp; my @aa=split/\t/,$_;
    my @cc=&methyl_level_c($aa[0],$aa[1],$aa[2]);#向子程序1传递三个参数chr,start,end
    my @dd=&methyl_level_s($aa[0],$aa[1],$aa[2]);#向子程序2传递三个参数chr,start,end
    $hash_c{$aa[0]}{"$aa[1]"."-"."$aa[2]"}=[$aa[3],$aa[4],$aa[5],$aa[6],$aa[7],$aa[8],$aa[9],$cc[0],$cc[1],$cc[2]];
    $hash_s{$aa[0]}{"$aa[1]"."-"."$aa[2]"}=[$dd[0],$dd[1],$dd[2]];
    }
    这个脚本的目的是给子程序传递染色体号,DMR起始和中止位置,然后获得这个DMR区间内每个样品的甲基化水平。
    每个样品的甲基化水平存放在两个matrix中,分别为control和stress.
    
    子程序1
    
    sub methyl_level_c{
    
    
    my @a;
    my @b;
    my $f0;
    my $f1;
    my $f2;
    my $f0_cg=0;
    my $f1_cg=0;
    my $f2_cg=0;
    my $f0_level=0;
    my $f1_level=0;
    my $f2_level=0;
    
    open MATC,"$ARGV[1]";#打开control_matrix.txt
    <MATC>;#去表头
    
    while(<MATC>){ 
       chomp; @a=split/\t/,$_;
          if($_[0]=~/$a[0]/ && $a[1]>=$_[1] && $a[1]<=$_[2]){ #匹配染色体号,界定DMR起始和终止位置的CG位点
                        foreach my $pos(2..10){
                              @b=split/,/,$a[$pos];#依次分割每个样品,取第一个值为该样品的该CG位点甲基化水平
                               if($pos<=4){if($b[0] ne "-"){$f0_cg+=1;$f0_level+=$b[0];}} #第2 3 4 列为第一组3个实验重复
       elsif($pos>=5 and $pos<=7){if($b[0] ne "-"){$f1_cg+=1;$f1_level+=$b[0];}}#第5 6 7 列为第二组3个实验重复
       elsif($pos>=8 and $pos<=10){if($b[0] ne "-"){$f2_cg+=1;$f2_level+=$b[0];}}#第57 8 9 列为第三组3个实验重复
       }
    }
    #遍历一个DMR区间内的每个样品三个实验重复的每个CG位点甲基化水平并相加存储到$(group)_level中,同时统计参与计算的CG位点数$(group)_cg。
    #下方为计算这个DMR的平均甲基化水平,测序深度为0的不参与计算,用“-”表示,如下
    
    if($f0_cg!=0){$f0=$f0_level/$f0_cg;}else{$f0="-";};
    if($f1_cg!=0){$f1=$f1_level/$f1_cg;}else{$f1="-";};
    if($f2_cg!=0){$f2=$f2_level/$f2_cg;}else{$f2="-";};
    
    }
    return $f0,$f1,$f2; #返回每个组的每个DMR的甲基化水平
    close MATC;
    }
    
    子程序2 与子程序1完全相同,只不过参与遍历的文件句柄由MATC变为了MATS
    
    sub methyl_level_s{
    
    
    my @a;
    my @b;
    my $f0;
    my $f1;
    my $f2;
    my $f0_cg=0;
    my $f1_cg=0;
    my $f2_cg=0;
    my $f0_level=0;
    my $f1_level=0;
    my $f2_level=0;
    open MATS,"$ARGV[2]";
    <MATS>;
    while(<MATS>){
    chomp;
    @a=split/\t/,$_;
    
    
    if($_[0]=~/$a[0]/ && $a[1]>=$_[1] && $a[1]<=$_[2]){
       
     foreach my $pos(2..10){
       @b=split/,/,$a[$pos];
                      if($pos<=4){if($b[0] ne "-"){$f0_cg+=1;$f0_level+=$b[0];}}
       elsif($pos>=5 and $pos<=7){if($b[0] ne "-"){$f1_cg+=1;$f1_level+=$b[0];}}
       elsif($pos>=8 and $pos<=10){if($b[0] ne "-"){$f2_cg+=1;$f2_level+=$b[0];}}
       }
    
    }
    if($f0_cg!=0){$f0=$f0_level/$f0_cg;}else{$f0="-";};
    if($f1_cg!=0){$f1=$f1_level/$f1_cg;}else{$f1="-";};
    if($f2_cg!=0){$f2=$f2_level/$f2_cg;}else{$f2="-";};
    
    }
    return $f0,$f1,$f2;
    close MATS;}
    

    相关文章

      网友评论

          本文标题:2019-08-08 perl 子程序 重复打开文件句柄

          本文链接:https://www.haomeiwen.com/subject/yjkxjctx.html