ikhan has asked for the wisdom of the Perl Monks concerning the following question:

Hi Perlmonks

I am trying to read multiple sequential files and

writing to corresponding output files. My code

creates the output files but data is written to only

the first file

#!/usr/bin/perl use strict; use warnings; my $begin_flag=0; my $end_flag=0; my $blank_line=0; my $begin_count=0; for my $i (1.. 3) { open(my $file1, '<', "input_$i.txt"); open(my $file2, '>', "output_$i.txt"); while(my $line= <$file1>) { $begin_flag =1 if($line =~ /^x/); $end_flag =1 if($line =~ /^y/); if($begin_flag==1 && $end_flag==0 && $begin_count++ >0) { print $file2 $line if($line !~ /^\s*$/); } } close $file1; close $file2; }

Replies are listed 'Best First'.
Re: multiple files to multiple files
by Corion (Patriarch) on Oct 18, 2015 at 07:05 UTC

    You should check that opening your files succeeds:

    open(my $file1, '<', "input_$i.txt") or die "Couldn't read from 'input_$i.txt': $!"; open(my $file2, '>', "output_$i.txt") or die "Couldn't write to 'output_$i.txt': $!";

    If opening $file1 fails, you will never enter the loop and thus won't write anything to $file2.

    You might also want to add some progress output to your loop.

Re: multiple files to multiple files
by Laurent_R (Canon) on Oct 18, 2015 at 09:57 UTC
    I think the problem might be with your use of the $begin_flag and $end_flag flags: they are set to 0 at the beginning of your program, and then presumably set to 1 in the course of reading the first file (if the patterns are matched), but are never reset to 0, so that when you read the second file, $end_flag is 1 and you never enter into the print instruction for the subsequent files.

    Note that the $begin_count variable is also never reset, and this is presumably not what you want. But we would need to see samples of your files to ascertain what you need to do.

Re: multiple files to multiple files
by bagyi (Acolyte) on Oct 18, 2015 at 07:26 UTC
    if($begin_flag==1 && $end_flag==0 && $begin_count++ >0) { print $file2 $line if($line !~ /^\s*$/); }
    You probably wants to chomp on $line before doing reggae match /^\s*$/;
      Although chomping input lines is often a good idea, I don't think it is necessary here, because the \s regex meta-character matches new line and carriage return characters:
      DB<1> $line = "foo bar\n"; DB<2> print $line if $line !~ /^\s*$/; foo bar DB<3> $line = " \t \r \n"; DB<4> print $line if $line !~ /^\s*$/; DB<5>
      Checking for the status of the open sys calls is the most urgent thing to do.
        Checking for the status of the open sys calls is the most urgent thing to do.

        "autodie to the rescue!" ;-)

        Just add use autodie qw( open close ); to the script. It will replace the core open and close functions with wrappers that automatically check for errors.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)