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

I need to seperate lines of a file into seperate files according to the first several characters in the original file. Example: original file contains:
host1 BUNCHOFDATAINALINE host2 BUNCHOFDATAINALINE host1 BUNCHOFDATAINALINE host2 BUNCHOFDATAINALINE
each entry of BUNCHOFDATAINALINE has a line break after, but its not printing right in this post... I want to seperate this into two files, called host1 and host2, containing the BUNCHOFDATAINALINE in the order it was originally in in the original file. I am a newbie to perl, but not so new as to know this IS possible. Thanks o great ones...

Replies are listed 'Best First'.
Re: Seperating individual lines of a file
by chargrill (Parson) on Feb 02, 2006 at 21:55 UTC

    You can put your sample data inside <code></code> tags.

    It would also be helpful if you put the code you've attempted for this inside those tags, too, so we can see where your code is not doing what you expect.



    --chargrill
    $/ = q#(\w)# ; sub sig { print scalar reverse join ' ', @_ } + sig map { s$\$/\$/$\$2\$1$g && $_ } split( ' ', ",erckha rlPe erthnoa stJu +" );
      Here my start on the code:
      #!/usr/bin/perl open ORIGFILE, "noc.060202_13"; #print ORIGFILE; push(@DATA,<ORIGFILE>); foreach my $LINE (@DATA){ open FH, "$LINE[0]"; print FH $LINE; close FH; }
      after setting up the foreach loop, i can print $LINE to STDOUT and see each line, but i cant pull out the first element as $LINE[0] to name the file, seemingly.

        First, that's an interesting use of push - you could just do @DATA=<ORIGFILE>;, but I don't think that's a big deal.

        Second, you'll find that you'll want to open your file for writing by using the open, FILEHANDLE, ">filename" nomenclature.

        Third, as written, your code will open a file called "host1 BUNCHOFDATAINALINE". You might want to split( /pattern/, expression ) each line of the file so you can separately refer to the separate pieces of data, like ( $HOSTNAME, $SOMEDATA ).



        --chargrill
        $/ = q#(\w)# ; sub sig { print scalar reverse join ' ', @_ } + sig map { s$\$/\$/$\$2\$1$g && $_ } split( ' ', ",erckha rlPe erthnoa stJu +" );
        Something that chargrill didn't mention, but might be an issue:

        Doing a file open and file close for every line can get really expensive and time consuming if there happen to be thousands of lines of input.

        Perl allows you to store file handles in a hash, so you can open a new file each time you see a new "hostname" string, and just re-use that handle whenever you see the same name again:

        # set $listfile to some constant, or to $ARGV[0] (and supply the file +name # as a command-line arg when you run the script) my %outfh; # hash to hold output file handles open ORIGFILE, $listfile or die "$listfile: $!"; while ( <ORIGFILE> ) { my ( $host, $data ) = split " ", $_, 2; if ( ! exists( $outfh{$host} )) { open( $outfh{$host}, ">", $host ) or die "$host: $!"; } print $outfh{$host} $data; } # perl will flush and close output files when done
        Of course, if there are lots of different host names in the input file (or if there is something really wrong and unexpected in the list file contents), the script would die when it tries to open too many file handles.

        People generally do

        use strict; use warnings;

        nowadays, and that's the single best piece of advice I can give you!

        Also, people do

        my @DATA=<ORIGFILE>;

        but then they also prefer to avoid slurping in files all at once, and they iterate on the lines instead with a while loop rather than with a for one:

        while (my $line=<ORIGFILE>) { # ...

        In any case you have to specify '>' mode in open for writing (and '>>' for appending). More generally I recommend you to stick with the three args form of open and lexical handles, and always check the return value:

        open my $in, '<', "whatever" or die "can't open `whatever': $!\n"; open my $out, '>', "whatever" or die "can't open `whatever': $!\n";
Re: Seperating individual lines of a file
by smokemachine (Hermit) on Feb 03, 2006 at 01:00 UTC
    perl -ne 'open(FILE, ">>".$1) if /^(.*?)\s(.*)$/; print FILE $2."\n"; +close FILE' data_file
      Interesting because golfed, although not to the extreme. But the OP should be warned about this circumstance. More importantly, and worth repeating, graff's comment applies to your solution as well.