#! /usr/bin/perl -w use strict; sub blocks { my $fh = shift; my $blocksize = shift || 8192; sub { return unless read $fh, my($block), $blocksize; return $block; } } sub records { my $blocks = shift; my $terminator = @_ ? shift : quotemeta($/); my @records; my ($buf, $finished) = (""); sub { while (@records == 0 && ! $finished) { if (defined(my $block = $blocks->())) { $buf .= $block; my @newrecs = split /($terminator)/, $buf; while (@newrecs > 2) { push @records, shift(@newrecs).shift(@newrecs); } $buf = join "", @newrecs; } else { @records = $buf; $finished = 1; } } return shift(@records); } } my $iter_block = blocks(\*DATA, shift || 10); my $iter_record = records($iter_block, "(?:foo\n)+"); while (my $record = $iter_record->()) { print "GOT A RECORD:\n$record\n"; } __DATA__ hello foo foo foo world foo foo foo !