-2

これが以前の議論ですでに回答されている場合、私はperlにまったく慣れていないのでお詫びします。ループ外で宣言された変数を使用する必要があるスクリプトがありますが、ループ外で変数を宣言したにもかかわらず、1 つのループしか機能していません。コードは次のとおりです。

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

等..

誰でもこれを理解できますか?

ありがとう

4

2 に答える 2

2

あなたのコメントから、あなたの問題はおそらくあなたが宣言$fastq1$fastq2てループの中にいることだと思います。つまり、ループの外側ではスコープ外になり、アクセスできなくなります。次のようなものが必要です。

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

これは、その変数のループの最後の値のみを保存することに注意してください。もちろん、他のものはループの反復ごとに上書きされます。保存する値が他にもある場合は、配列またはハッシュを使用してください。

コードに関するその他の注意事項。


常に使用する必要があります

use strict;
use warnings;

そうしないことは非常に悪い考えです。それはエラーと警告を隠すだけであり、それらを解決しないからです。


my $sample;

この変数を2回宣言します。


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その値は1回のループ反復でのみ保持されます。この変数を使用することは決してないので、ループの外で使用するつもりだったと思います。しかし、それはそこでは範囲外になります。

これは書くことができます

my $fastq1 = $sample;

ただし、これらの変数をwhileループの外で宣言したい場合があります。そうしないと、変数の範囲外になります。もちろん、これはこれらの変数の最後の値のみを保存することを知っておく必要があります。


また、Rohitが言うように、ループはネストされていますが、これはあなたが望んでいたものではないと思います。これは、コードの記述に適切なテキストエディターを使用していないために発生する可能性が高く、インデントがすべて台無しになり、1つのループがどこで終了するかを確認するのが困難です。そこでRohitのアドバイスに従ってください。

于 2013-02-19T17:00:07.557 に答える
1

2番目のwhileループが終了した後、最初のwhileループを閉じています。そのため、2番目のwhileループは1番目の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
于 2013-02-19T16:36:33.220 に答える