use strict; use warnings; use File::Slurp; use constant { CHUNK_LIMIT => 500 * 1024, EXCEPTION_LIMIT => 25 * 1024 * 1024, }; my $in_filename = 'infile.dat'; # Filename generators { my $filenumber = 0; sub next_output_filename { return sprintf('outfile_%03d.dat', $filenumber++); } } { my $filenumber = 0; sub next_special_filename { return sprintf('special_%03d.dat', $filenumber++); } } { my $outfile_buffer = ''; sub write_invoice { my ( $invoice, $force_flush ) = @_; my $invoice_len = length $invoice; my $buffer_len = length $outfile_buffer; # If the invoice is special, write it immediately to # a Special file, bypassing the $outfile_buffer queueing. if ( $invoice_len >= EXCEPTION_LIMIT ) { write_file( next_special_filename(), $invoice ); return 1; } # If the invoice would made the $outfile_buffer too # big, flush it. my $too_big = $buffer_len + $invoice_len >= CHUNK_LIMIT; if ( $too_big or $force_flush ) { if ( $buffer_len ) { write_file( next_output_filename(), $outfile_buffer ); $outfile_buffer = ''; } } # Store the invoice with the rest waiting to be # written to file. $outfile_buffer .= $invoice if $invoice; return 1; } } open my $in_fh, '<', $in_filename or die "Can't open '$in_filename': $!"; my $invoice = ''; while ( <$in_fh> ) { if ( length($_) >= 69 and substr( $_, 67, 2 ) eq '11' ) { write_invoice( $invoice ); $invoice = ''; } $invoice .= $_; } close $in_fh or warn "Can't close '$in_filename': $!"; write_invoice( $invoice ) if $invoice; write_invoice( '', 'FORCE' );