66925


**複数のファイルに違う内容を書き込む**  
Perlを使って複数ファイルにそれぞれ違う内容を書き込みたいです。

具体的には、コマンドライン入力した$start_no=2、入力ファイルの行数が 3 とすると  
tmp1.txtに 2 3 4 5  
tmp2.txtに 6 7 8 9  
....  
と書き込みたいです。

以下のコードでは、指定した出力ファイルtmp1~4.txt自体はつくられますが、中にはなにも書き込まれません。  
余分と判断した部分は削除しているため、入力ファイル内の値はここでは何も使われていません。

[code]

    my $infile=$ARGV[0];
    my $start_no=$ARGV[1];
    
    open (my $infh,'<',$infile);
    
    my $i=0;
    my $j;
    for ($j=1;$j<5;$j++){
      my $outfile1="tmp1.txt";
      my $outfile2="tmp2.txt";
      my $outfile3="tmp3.txt";
      my $outfile4="tmp4.txt";
    
      open (my $outfl1,'>',$outfile1);
      open (my $outfl2,'>',$outfile2);
      open (my $outfl3,'>',$outfile3);
      open (my $outfl4,'>',$outfile4);
        while ( my $line= <$infh>) {
        $i++;
        if ($i == 1){
        next;#skip label
        }
    
        my $line_no1=2*($start_no-2)+2;
        my $line_no2=$line_no1+1;
        if($j==1){
        print $outfl1 "$line_no1 \n";
        print $outfl1 "$line_no2  \n";
        }
        elsif($j==2){
        print $outfl2 "$line_no1  \n";
        print $outfl2 " $line_no2 \n";
        }
        elsif($j==3){
        print $outfl3 "$line_no1 \n";
        print $outfl3 "$line_no2  \n";
        }
        else{
        print $outfl4 "$line_no1 \n";
        print $outfl4 " $line_no2  \n";
        }
        $start_no++;
        }
      close ($outfl1);
      close ($outfl2);
      close ($outfl3);
      close ($outfl4);
    }
    close ($infh);
    
[/code]

**試したこと**  
出力ファイルに書き込む前に print $outfl1; とすると、GLOB(0x2208c38) と表示されます。


CC BY-SA 4.0
2020-05-22T04:35:36.910
66869
2020-05-23T15:02:21.123
40283
question
perl
Perlを用いて複数のファイルにそれぞれ違う内容を書き込む方法について


原因はforループが回る度にopen/closeで全てのファイルを上書きしているからです。  
if文でprintを回避しても上書きモード(`>`)で開かれたファイルは全て作り直されます。

[code]

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    # open/close失敗時に例外を投げるようにする。
    use autodie;
    
    my $infile   = $ARGV[0];
    my $start_no = $ARGV[1];
    
    # forループの中で毎回readline(`<$infh>`)を呼ぶのではなく
    # ループの前に$infileの行数を確定しておく。
    open(my $infh, '<', $infile);
    
    # 1. `() = <$infh>`
    #   <$infh>をリストコンテキストで評価すると
    #   ファイルの内容を行ごとの配列にして取り出すことができる。
    #   ただしこの場合行数が欲しいだけなので、配列は用意しない。
    # 2. `my $i = ()`
    #   配列をスカラコンテキストで評価すると
    #   配列の要素数を取り出せる。この場合$infileの行数。
    my $i = () = <$infh>;
    
    # 使わなくなったファイルハンドルは速やかにcloseする。
    close($infh);
    
    
    # 単純なインクリメントであれば、Cスタイルのforループを使うまでもない。
    # https://perldoc.jp/docs/perl/perlop.pod#Range32Operators
    for my $j (1 .. 4) {
        my $outfile = "tmp$j.txt";
        open(my $outfl, '>', $outfile);
    
        my $line_no1 = 2 * ($start_no - 2) + 2;
        my $line_no2 = $line_no1 + 1;
    
        print $outfl "$line_no1 \n";
        print $outfl "$line_no2  \n";
    
        $start_no++;
    
        close($outfl);
    }
    
[/code]


CC BY-SA 4.0
2020-05-23T15:02:21.123
66925
2020-05-23T15:02:21.123
62
66869
answer