-2

如果在之前的讨论中已经回答了这个问题,我对 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

ETC..

任何人都可以解决这个问题吗?

谢谢

4

2 回答 2

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 所说,您的循环是嵌套的,我认为这不是您想要的。这很可能是因为您没有使用适当的文本编辑器来编写代码,因此您的缩进全都搞砸了,而且很难看到一个循环在哪里结束。听从 Rohit 的建议。

于 2013-02-19T17:00:07.557 回答
1

您将在第二个 while 循环结束后关闭第一个 while 循环。因此,您的第二个 while 循环成为您的第一个 while 循环的一部分,其中,您将文件处理程序 - IN重新分配给不同的文件。而且由于您在内部 while 循环中耗尽了它,因此您的外部 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
于 2013-02-19T16:36:33.220 回答