Perl while循环不起作用

时间:2013-02-19 16:34:34

标签: perl loops while-loop

如果在之前的讨论中已经回答了这个问题,那我对perl和道歉很新。我有一个脚本需要在循环外使用声明的变量,但只有一个循环正在工作,即使我已经在循环之外声明了变量,代码是:

my $sample;
open(IN, 'ls /*_R1_*.gz |');
while (my $sample = <IN>) {
    chomp $sample;
    print "sample = $sample\n";
    my $fastq1="${sample}"; #need to use fastq1 later on hence it's declared here

    my $sample2;
    open(IN, 'ls /*_R2_*.gz |');
    while (my $sample2 = <IN>) {
        chomp $sample2;
        print "sample2 = $sample2\n";
        my $fastq2="${sample2}"; #need to use fastq2 later on hence it's declared here
    }
}

Sample2有效但sample1没有,只输出第一个样本,然后循环进入sample2,输出为:

sample =/sample1_R1_001.fastq.gz
sample2 =/sample1_R2_001.fastq.gz
sample2 =/sample2_R2_001.fastq.gz
sample2 =/sample3_R2_001.fastq.gz

等。

有人可以解决这个问题吗?

由于

2 个答案:

答案 0 :(得分:2)

根据您的评论,我认为您的问题可能是您在循环中声明$fastq1$fastq2。这意味着它们将超出循环范围,并且无法访问。你需要这样的东西:

my ($fastq1, $fastq2);
while ( ... ) {
    ....
    $fastq1 = $sample;
}

请注意,这只会保存该变量循环中的最后一个值。当然,其他循环迭代将覆盖其他循环。如果要保存更多值,请使用数组或散列。

关于您的代码的其他一些注释。


你应该总是使用

use strict;
use warnings;

不这样做是一个非常糟糕的主意,因为它只会隐藏错误和警告,而不是解决它们。


my $sample;

您将此变量声明两次。


open(IN, 'ls /*_R1_*.gz |');

这在所有可能的级别上都很糟糕:

  • 系统调用始终是最不可取的选项,除非没有其他选择
  • Perl有许多方式读取文件名
  • 解析ls的输出很脆弱且不便携
  • 通过open打开系统命令的结果正在加剧这种方法的其他缺陷。

推荐的解决方案:使用opendir + readdir或glob:

for my $files (</*_R1_*.gz>) { ... }
# or
opendir my $dh, "/" or die $!;
while (my file = readdir $dh) { 
    next unless $file =~ /_R1_.*\.gz$/;
    ...
}

my $fastq1 = "${sample}"; 
  • 您不需要引用变量。也不使用支撑花括号。
  • 在循环内声明带my的变量时,它只保留单循环迭代的值。既然你从不使用这个变量,我认为你打算在循环之外使用它。但它将超出范围。

这可以写成

my $fastq1 = $sample;

但是您可能希望在while循环之外声明这些变量,否则它们将超出范围。你应该知道,这只会保存这些变量的最后一个值。


另外,正如Rohit所说,你的循环是嵌套的,我认为这不是你想要的。这很可能是因为你没有使用正确的文本编辑器来编写你的代码,所以你的缩进都搞砸了,很难看出一个循环结束的地方。遵循罗希特的建议。

答案 1 :(得分:1)

您正在关闭第二个while循环结束后的第一个while循环。因此,您的第二个while循环成为第一个while循环的一部分,其中,您将文件处理程序 - IN 重新分配给另一个文件。而且由于你在内部while循环中耗尽它,你的外部while循环永远不会再次运行。

你应该在开始下一个之前关闭大括号:

while(my $sample = <IN>){
    chomp $sample;
    print "sample = $sample\n";
    my $fastq1="${sample}";
}  # You need this

my $sample2;
open(IN, 'ls /data_n2/vmistry/Fluidigm_Exome/300bp_fastq/*_R2_*.gz |');
while(my $sample2 = <IN>){
    chomp $sample2;
    print "sample2 = $sample2\n";
    my $fastq2="${sample2}";

}
# }  # Remove this