2

最初に、ここでの書式設定が間違っている場合はお詫びします。スクリプトを書くのは初めてで (3 日)、このサイトでの最初の投稿です。

タブで区切られ、File a14 列をFile b含み、8 列を含む 2 つのファイルがあります。

の 1 つの列にFile bは、 の 2 つの数値フィールドによって生成された数値の範囲に相関する数値が含まれていますFile a。のすべての行についてFile a、 を検索し、File b両方のファイルのフィールドからデータの組み合わせを出力する必要があります。File a数値範囲が受け入れられるため、 の各行に複数の一致があります。

私が作成したコードは、私がやりたいことを正確に実行しますが、 の最初の行のみでありFile a、ループを続行しません。私はインターネット全体を見てきましたが、両方のファイルが標準入力から読み取られているという事実に関係していると思います。この問題を修正しようとしましたが、何も機能しないようです

>$3私の現在の理解では、あるファイルを別のファイル記述子から読み取るように変更することで、ループが機能する可能性があります... または、grep私も苦労している機能を使用している可能性があります。

現在使用しているコードの概要は次のとおりです。

use strict;  
use warnings;

print "which file read from?\n";
my $filea = <STDIN>;  
chomp $filea;  
{
  unless (open ( FILEA, $filea) {
      print "cannot open, do you want to try again? y/n?\n?";  
      my $attempt = <STDIN>;  
      chomp $again;  
      if ($again =~ 'n') {
          exit;  
      } else {
          print "\n";   
          $filea = <STDIN>;  
          chomp $filea;  
          redo;  
      }
   }
}

#I also open fileb the same way, but wont write it all out to save space and your time.

my output = 'output.txt';  
open (OUTPUT, ">>$output");    

while (my $loop1 = <FILEA>) {  
    chomp $loop1;
    ( my $var1, my $var2, my $var3, my $var4, my $var5, my $var6, 
      my $var7, my $var8, my $var9, my $var10, my $var11, my $var12, 
      my $var13, my $var14 ) = split ( "\t", $loop1);

  #create the range of number which needs to be matched from file b.
  my $length = length ($var4);  
  my $range = ($var2 + $length);

  #perform the search loop through fileb
  while (my $loop2 = <FILEB>) {
      chomp $loop2;
    ( my $vala, my $valb, my $valc, my $vald, my $vale, my $valf, 
      my $valg) = split ( "\t", $loop2 );

    #there are then several functions and additions of the data, which all work basicly so I'll just use a quick example.

    if ($vald >= $val3 $$ $vald <= $range) {
        print OUTPUT "$val1, $vald, $val11, $valf, $vala, $val5 \n";
    }
  }
}

これがすべて理にかなっていることを願っています。ループがファイル全体で続くようにコードを編集するのを手伝ってくれる人がいれば、すべてをできるだけ明確にしようとしました。

可能であれば、あなたがしたことを説明してください。コードをあまり変更せずにこの結果を得ることができれば理想的です。

みんなありがとう!!!

4

1 に答える 1

2
  1. 可能であれば裸のハンドルは避けてください。FH の代わりに $fh (ファイルハンドル) を使用する

  2. until の代わりに until を使用して、やり直しをスキップできます。

    print "Enter the file name\n";
    my $file_a = <STDIN>;
    chomp $file_a;
    my $fh_a;
    until(open $fh_a, '<', $file_a) {
        print "Re-enter the file name or 'n' to cancel\n";
        $file_a = <STDIN>;
        chomp $file_a;
        if($file_a eq 'n') {
            exit;
        }
    }
    
  3. これらすべての個々の列変数の代わりに配列を使用できます (すべきです)。my @cols_a = split /\t/, $line;

  4. ファイル B を配列に 1 回読み取ってから、次のことが必要になるたびにその配列を検索する必要があります。my @file_b = <$fh_b>;

  5. 結果は次のようになります。

    #Assume we have opened both files already . . .
    my @file_b = <$fh_b>;
    chomp @file_b;
    while(my $line = <$fh_a>) {
        chomp $line;
        my @cols_a = split /\t/, $line;
        #Remember, most arrays (perl included) are zero-indexed,
        #so $cols_a[1] is actually the SECOND column.
        my $range = ($cols_a[1] + length $cols_a[3]);
    
        foreach my $line_b (@file_b) {
            #This loop will run once for every single line of file A.
            #Not efficient, but it will work.
            #There are, of course, lots of optimisations you can make
            #(starting with, for example, storing file B as an array of array
            #references so you don't have to split each line every time)
            my @cols_b = split /\t/, $line_b;
            if($cols_b[3] > $cols_a[2] && $cols_b[3] < ($cols_a[2] + $range)) {
                #Do whatever here
            }
        }
    }
    
于 2013-10-03T20:29:46.217 に答える