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

Hi, I am trying to read a text file and split up the file into maybe 10 smaller files. I am new to perl and have come up with a very ugly code. Was wondering if anybody can help me improve on the code by using loops? Code as below:
---------------------------------------------------- #!/usr/bin/perl -w # print_line-v1 - linear style $i=1; while ($i<=10) { $file=("temp".$i); $dfile=("temp".$i.".txt"); open($file,">>$dfile") || die "Can not open $dfile: $!"; #print("$file \n"); #print("$dfile \n"); $i++; } open(HOSTCOUNT,"$ARGV[0]"); @hosts=<HOSTCOUNT>; $count=@hosts; $line_number = ($count / 10); $line_number = int($line_number); @ARGV == 1 or die "usage: print_line FILENAME line_number\n"; ($filename) = @ARGV; open(HOSTS, "< $filename") or die "Can't open $filename for reading: $ +!\n"; while (<HOSTS>) { $line = $_; $j=$line_number+1; last if $. == $j; print temp1 ("$. $line"); } last if $. == $line_number+2; print temp1 ("$. $line"); while (<HOSTS>) { $line_number2=($line_number+$line_number+1); $line = $_; last if $. == $line_number2; print temp2 ("$. $line"); } last if $. == $line_number2+1; print temp2 ("$. $line"); while (<HOSTS>) { $line_number3=($line_number2+$line_number+1); $line = $_; last if $. == $line_number3; print temp3 ("$. $line"); } last if $. == $line_number3+1; print temp3 ("$. $line"); while (<HOSTS>) { $line_number4=($line_number3+$line_number+1); $line = $_; last if $. == $line_number4; print temp4 ("$. $line"); } last if $. == $line_number4+1; print temp4 ("$. $line"); while (<HOSTS>) { $line_number5=($line_number4+$line_number+1); $line = $_; last if $. == $line_number5; print temp5 ("$. $line"); } last if $. == $line_number5+1; print temp5 ("$. $line"); while (<HOSTS>) { $line_number6=($line_number5+$line_number+1); $line = $_; last if $. == $line_number6; print temp6 ("$. $line"); } last if $. == $line_number6+1; print temp6 ("$. $line"); while (<HOSTS>) { $line_number7=($line_number6+$line_number+1); $line = $_; last if $. == $line_number7; print temp7 ("$. $line"); } last if $. == $line_number7+1; print temp7 ("$. $line"); while (<HOSTS>) { $line_number8=($line_number7+$line_number+1); $line = $_; last if $. == $line_number8; print temp8 ("$. $line"); } last if $. == $line_number8+1; print temp8 ("$. $line"); while (<HOSTS>) { $line_number9=($line_number8+$line_number+1); $line = $_; last if $. == $line_number9; print temp9 ("$. $line"); } last if $. == $line_number9+1; print temp9 ("$. $line"); while (<HOSTS>) { $line_number10=($line_number9+$line_number)+1; $line = $_; last if $. == $line_number10; print temp10 ("$. $line"); } last if $. == $line_number10+1; print temp10 ("$. $line"); ----------------------------------------------------
I am having problems with looping because the script will always skipped 1 line. Thanks!

Replies are listed 'Best First'.
Re: split a file to several smaller file
by ikegami (Patriarch) on Dec 11, 2007 at 07:22 UTC
    my $count = 0; my $fh_out; while (<$fh_in>) { if (!defined($fh_out)) { my $fname = sprintf('%s-%d.%s', $base, $count++, $ext); open($fh_out, '>', $fname) or die("Unable to create \"$fname\": $!\n"); } print $fh_out $_; if ($. % $num_lines == 0) { undef($fh_out); } }

    Update: Fixed typo mentioned in reply.

      Slight typo, should be $! instead of $1 (<shift> key):
      or die("Unable to create \"$fname\": $!\n");
      Hi, I have error when i run this.. could you give me more information as in what is $base and $ext? sorry.. i'm new to perl.. thanks!

        $base is the base name of all of the files, such as the log part of log001.txt, log002.txt, and log003.txt. $ext is the file extension, or txt in the example here.

      thanks.. and what is $fh_out? $fh_in is the text file it is reading right? Now there is no errors but I am not spawning any files.. there is no output..

        Did you actually open a file and assign the handle to $fh_in?

        open(my $fh_in, '<', $qualified_name) or die("Unable to open file \"$qualified_name\" to split: $!\n");

        and what is $fh_out? $fh_in is the text file it is reading right?

        Yes, except that these are "file handles" rather than the actual file in any sense, (hence the naming convention "fh").

        Does that make sense? If you do a close $fh_out; the file doesn't go away, just perl's ability to write to the file via that particular handle.

        Thanks for the explaination of file handler.. it make sense.. i did specified a fh_in. but i'm still not sure what does fh_out do? we have $base and $ext to work out the file name of the output so what does fh_out do?
      hey.. it is working now.. thank guys! great help!
Re: split a file to several smaller file
by apl (Monsignor) on Dec 11, 2007 at 12:37 UTC
    If you're using *nix, I'd suggest you do a man split, and bypass Perl.
Re: split a file to several smaller file
by andreas1234567 (Vicar) on Dec 11, 2007 at 13:41 UTC
    There is a module called File::Split, but unfortunately it depends on Array::Dissect which has been withdrawn from CPAN (as noted in this bug). The source for File::Split is still available, which is convenient if you want to write your own.
    --
    Andreas