2016-05-10 6 views
1

私は2,000を超えるサブディレクトリのそれぞれの中で "pairsAngles.txt"から "Distance:"という文字列をgrepしようとしていました。サブディレクトリの名前はcsvファイルから取得されます。しかし何らかの理由でforeach()はループの始めからすべてを再起動します。私は、問題の原因となっているステップわからない enter image description here どうやらすべての距離が1列にすることになっている...Perl:foreachで再起動するための冗長性?

:だから、出力は次のようになります。 コードを次のように

#!/usr/bin/perl -w 
use strict; 
use warnings; 
use File::Find; 
use List::MoreUtils qw(uniq); 
use Cwd qw(cwd); 
use Text::CSV_XS; 
use Data::Dumper; 

my @pairs=qw(); 
my @result=(); 

my $in; 
my $out; 
my $pairs; 
my $dist = ""; 
my $dir = "/home/avabelieve/aaPROJECT/helicalPair_ax/selectedPairs/renumberedPdb/clusterPairs-1.25-12-05_windows.12.resle3.2A.RMSD1.3/oligomerAngle"; 

my $cluster = "clst1.csv"; 
open ($in, $cluster) || die "cannot open \"$cluster\": $!"; 

my $cU = "clst1Updated.csv"; 
open ($out, ">$cU") || die "cannot open '$cU' $!"; 

my $csv = Text::CSV_XS->new ({ binary => 1, auto_diag => 1, eol => $/ }); 

while (my $c1 = <$in>) {  
    chomp $c1; 
    push @pairs, $c1; 

    foreach $c1 (uniq @pairs) { 
     find (\&Matches, "$dir/$c1"); 
     sub Matches { 
      open ($pairs, "pairsAngles.txt") or die "$!"; 

      while (my $dist = <$pairs>) { 

       if ($dist =~ m/Distance: /) {      

        chomp $dist; 
        push (@result, "$dist\n"); 
        @result = split "\t", $dist; 
       }    

      } 
     } 
    } 
    chdir ".."; 

    if (not $csv->eof) { 
     $csv->error_diag(); 
    } 
    $csv->say ($out, [uniq @pairs, @result]); 
} 
close $out or die "$!"; 
+0

「* foreach()はすべてのループの先頭から再起動します」と...「何の始まり?そして、そのループの始まりは?私はあなたが何を意味するか知っていると思いますが、あなたは明確にすることができますか? – Schwern

+0

すべてのサブディレクトリ名を含むcsvファイルの先頭。 –

答えて

2

whileループが@pairsのリストに追加されます。

while (my $c1 = <$in>) {  
    chomp $c1; 
    push @pairs, $c1; 

foreachループがこれらのペアを繰り返します。

foreach $c1 (uniq @pairs) { 
    find (\&Matches, "$dir/$c1"); 

foreachループはwhileループ内にあるので、ペアはforeachループ@pairsに追加されるたびに先頭からすべてやり直す成長を続ける@pairsを反復します。

これを避けるには、ビルド@pairsを完成させ、それをループオーバーします。

while (my $c1 = <$in>) {  
    chomp $c1; 
    push @pairs, $c1; 
} 

foreach $c1 (uniq @pairs) { 
    find (\&Matches, "$dir/$c1"); 
    ... 
} 

ちなみに、そのwhileループは、より良いリストに取り組んでchompの利点を活用するために書き込むことができます。

my @pairs = <$in>; 
chomp @pairs; 
+0

whileループの変更は実際には機能しませんでした...また、出力はオンラインに戻りました...第3の質問を参照してください:http://stackoverflow.com/questions/37149051/perl-output-still-only一直線 –

1

私のための2つの不可解な場所があります。

(1)@pairsに入力行を追加します(push @pairs, $c1)。しかし、毎回すべて(ユニーク)のペアを処理します。つまり、コードで以前に処理されたすべてのペアを最初に再処理し、それを追加します。それは意図されていますか?このようにして、繰り返しの結果が得られるようです。代わりに、ペアを収集し、複製を整理してから処理することができます。

my @pairs = uniq <$in>; # chomp if needed, chomp(@pairs) 
foreach $c1 (@pairs) { ... } 

(2)コードが@result$distを追加 - しかし、それは@resultに代入することによって、その上書き。

push (@result, "$dist\n"); 
@result = split "\t", $dist; 

これもまた意図していますか?

+0

良い点。それは間違いなく意図されていた...私は入力csvファイルからすべてのサブディレクトリ名(@ペア)を取得してgrepを実行しようとしていた。実際には、すべてのサブフォルダ名が一意であるため、「uniq」はここでは必要ありません。しかし、私は重複した結果を受け取りました... –

+0

ああ、その後、より良いuniqを落としてください。あなたが(処理に応じて)どちらかをchompする必要はないことに注意してください。 2番目の点も有効です。コードは '@ result'を2回変え、矛盾した方法で変更します。これらのうちの1つは必要ありません。 2つ目は常に '@ result'全体を上書きします。 – zdim

+0

ありがとうzdim!私はシステムが私にあなたに緑色のチェックマークを与えることを可能にしたいと思います... –

関連する問題