Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

reading files to different output files.

by ic23oluk (Sexton)
on May 28, 2017 at 10:37 UTC ( [id://1191417]=perlquestion: print w/replies, xml ) Need Help??

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

hello, I'm new to Perl! I'd like to write a script that obtains a list of files from the command line, read the files, and write their content to different output files. Here's my code:

#! /usr/bin/perl use strict; use warnings; my $output = "output.txt"; open (WRITE, ">$output") || die $!; while (<>){ chomp $_; print WRITE "$_\n"; } print "done\n";

How can I automatically create as much output files as needed without assigning them by myself, so that it works with any number of input files? Thanks in advance!

Replies are listed 'Best First'.
Re: reading files to different output files.
by choroba (Cardinal) on May 28, 2017 at 11:32 UTC
    Use an array of output file handles. You can use an array of input file handles, too.

    Note that

    print $file_handles[$i] $line;

    doesn't work, you need to use curlies:

    print {$file_handles[$i]} $line;

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      is there any solution using this approach:

      use IO::File; my @fh; my @file_names = ("output1.txt", "output2.txt", "output3.txt"); for (my $i=0; $i<=$#file_names; $i++){ $fh[$i]= IO::File->new( ">$file_names[$i]" ) || die "Cannot open $ +file_names[$i]: $!.\n"; }
        Or, without any modules:

        my @fhs = map { open my $FH, '<', $_ or die $!; $FH } @filenames;

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
        What exactly is your problem now?

        Did you try it? And what went wrong?

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

      yes, but it didn't work. here's my entire script:

      #! /usr/bin/perl use strict; use warnings; use IO::File; my @fh; my @file_names = ("output1.txt", "output2.txt", "output3.txt"); while ( <> ){ for (my $i=0; $i<=$#file_names; $i++){ $fh[$i]= IO::File->new( ">$file_names[$i]" ) || die "Cannot op +en $file_names[$i]: $!.\n"; print {$fh[$i]} "$_"; } } print "done.\n";

      It produced three output files, each containing the command that i entered in the command line. What's missing?

        Why use <> if you allready have the array list?

Re: reading files to different output files.
by shmem (Chancellor) on May 28, 2017 at 14:23 UTC

    If you use the special null filehandle for reading multiple files on the command line (i.e. if you read via <>) , the name of the current input file will show up in the special variable $ARGV (see perlvar). You can use this variable to determine whether the file name has changed because the next file has been opened, and (re-)open the output filehandle to another file. Of course you have to provide means to change the output file name (e.g. a prefix or suffix applied to the input file name, or a counter), otherwise the same file will be re-opened and clobbered.

    Example:

    my $filename; # used to remember the current file name my $out = "output"; # prefix for output files my $ofh; # output filehandle, currently closed while (<>) { if ($ARGV ne $filename) { $filename = $ARGV; open $ofh, '>', "$out-$filename" or die "Can't write to '$out-$filename': $!\n"; } print $ofh $_; }
    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

      Okay, tried it again but it writes the names of the comman line input to the output files instead of the content of the input files. :/ Here's my code:

      my @fh; my @file_names = ("output1.txt", "output2.txt", "output3.txt"); my @in = <>; my $i = 0; open (READ, @in) || die "cannot open @in: $!.\n"; while ( <> ){ for (my $i=0; $i<=$#file_names; $i++){ $fh[$i]= IO::File->new( ">$file_names[$i]" ) || die "Cannot op +en $file_names[$i]: $!.\n"; print {$fh[$i]} "$_"; } } close (READ); print "done.\n";

      by now it feels like I'm mentally retarded :(

        To expand a bit on the correct diagnosis of Anonymous Monk, you are opening the files, but you are not reading from them.

        You are trying to read STDIN twice, once here:

        my @in = <>;

        and once here:

        while ( <> ){ ... }

        It's not clear to me what that is supposed to achieve.

        Then you try to open a filehandle to a list:

        open (READ, @in) || die "cannot open @in: $!.\n";

        This suggests that you only have a single filename in @in, and that filename does not have a newline appended.

        Your program logic alltogether is a bit weird, because in your while loop, you recreate your output files on every pass through the loop. This is most likely not what you want:

        while ( <> ){ for (my $i=0; $i<=$#file_names; $i++){ ... } }

        Let me suggest a different structure of your program:

        1. Open the output file(s)
        2. For each input file
        3. Open the input file
        4. Read one line from the input file
        5. Write the line to the output file(s)
        6. Repeat reading

        You have many parts of that already, but your program isn't structured in the right order.

        Did you understand the node you've been replying to? If not, please tell.

        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

        start with changing <> into <READ> to actually read the file, and drop the module IO::File, you don't need it. Furthermore @in should probably be $in to collect userinput.

        You are not reading any files.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1191417]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (3)
As of 2024-03-30 02:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found