( $match )= $string =~ /($pattern)/; #### package Stream::Match; sub new { my( $class, $stream, $pattern )= @_; return bless { str => $stream, # Stream to read from pat => $pattern, # Regex to find matches buf => "", # Stream data that might match later blk => 8*1024, # How many bytes to read each time }, $class; } sub nextMatch { my( $self )= @_; my $svBuf= \$self->{buf}; pos( $$svBuf )= 0; # Just in case my $res= 1; while( 1 ) { if( $res && length($$svBuf) < $self->{blk} ) { # Append more data from stream to $self->{buf}: $res= sysread( $self->{str}, $$svBuf, $self->{blk}, length($$svBuf) ); if( ! defined $res ) { die "Error reading from stream ($self->{str}): $!"; } } if( "" eq $$svBuf ) { return; # End of file } # Note that 0 == pos( $$svBuf ) my $match= $res ? $$svBuf =~ /$self->{pat}/zg : $$svBuf =~ /$self->{pat}/g; if( $match ) { # We got a match! # Copy the match (like $&): my $line= substr( $$svBuf, $-[0], $+[0]-$-[0] ); # Leave only $' in $self->{buf}: substr( $$svBuf, 0, $+[0], "" ); return $line; } my $pos= pos( $$svBuf ); if( ! defined $pos ) { # Didn't hit end-of-string: return; # This regex will NEVER match. } # Remove $self->{buf} chars that will never start a match: substr( $$svBuf, 0, $pos, "" ); } } package main; # Sample use that emulates the Unix "strings" command: binmode( STDIN ); my $o= Stream::Match->new( \*STDIN, qr/[\s -~]+(?=\0)/ ); my $string; while( $string= $o->nextMatch() ) { print "$string\n"; } #### __END__ # This is the code I originally posted package Stream::Match; sub new { my( $class, $stream, $pattern )= @_; return bless { str => $stream, # Stream to read from pat => $pattern, # Regex to find matches buf => "", # Stream data that might match later blk => 8*1024, # How many bytes to read each time }, $class; } sub nextMatch { my( $self )= @_; my $svBuf= \$self->{buf}; my $res; do { # Note that 0 == pos( $$svBuf ) if( $$svBuf =~ /$self->{pat}/zg ) { # We got a match! # Copy the match (like $&): my $line= substr( $$svBuf, $-[0], $+[0]-$-[0] ); # Leave only $' in $self->{buf}: substr( $$svBuf, 0, $+[0], "" ); return $line; } my $pos= pos( $$svBuf ); if( ! defined $pos ) { # Didn't read end-of-string: return; # This regex will NEVER match. } # Remove $self->{buf} chars that will never start a match: substr( $$svBuf, 0, $pos, "" ); # Append more data from stream to $self->{buf}: $res= sysread( $self->{str}, $$svBuf, $self->{blk}, length($$svBuf) ); } while( $res ); if( ! defined $res ) { die "Error reading from stream ($self->{str}): $!"; } return; # End of file } package main; # Sample use that emulates the Unix "strings" command: binmode( STDIN ); my $o= Stream::Match->new( \*STDIN, qr/[\s -~]+(?=\0)/ ); my $string; while( $string= $o->nextMatch() ) { print "$string\n"; }