#!/usr/bin/perl use constant CHUNK => 500 * 1024; # 500 KB use strict; use warnings; use List::Util 'sum'; my $file = $ARGV[0] or die "Usage: $0 "; open(my $in_fh, '<', $file) or die "Unable to open '$file' for reading: $!"; my ($cnt, @buffer); while (<$in_fh>) { if (is_new_invoice($_)) { my $size = sum(map length($_), @buffer); if ($size > CHUNK) { flush_buffer(); push @buffer, $_; } else { push @buffer, $_; } } else { $buffer[-1] .= $_; } } flush_buffer(); sub flush_buffer { # variables should probably be passed explicitly return if ! @buffer; ++$cnt; open ($out_fh, '>', "outfile.$cnt") or die "Unable to open 'outfile.$cnt' for writing: $!"; my $size = 0; while (1) { my $invoice = shift @buffer; last if ! $invoice; my $len = length($invoice); # If invoice by itself is larger than chunk, write to new file if ($len > CHUNK) { ++$cnt; open ($out_fh, '>', "outfile.$cnt") or die "Unable to open 'outfile.$cnt' for writing: $!"; print $out_fh $invoice; close $out_fh; next; } # If this $invoice puts the current file over the limit, close the current file if ($size + $len > CHUNK) { close $out_fh; # Replace the invoice back in the buffer and return if not end of input if (! eof $in_fh) { unshift @buffer, $invoice; } else { # Write out whatever is left ++$cnt; open ($out_fh, '>', "outfile.$cnt") or die "Unable to open 'outfile.$cnt' for writing: $!"; print $out_fh $invoice; close $out_fh; } return; } else { # Add this invoice to the existing open file print $out_fh $invoice; } last if ! @buffer; } } sub is_new_invoice { my ($line) = @_; return 1 if substr($line, 66, 2) eq '11'; return 0; }