in reply to Accepting either a filename or a handle

Alternatively, if you don't like the ref solutions, you can use one of perl's Obscure Open Tricks

sub your_function { my ( $string, $in_fh, $out ) = @_; local *OUTFH; # opens $out if it's a filename # dupes $out if it's a filehandle open OUTFH, ">$out" or die "$out: $!\n"; # do whatever with $in_fh and $string while( <$in_fh> ) { /$string/o and print OUTFH "$string: $_" } # close OUTFH: either we opened it or we duped it # Either way we don't need it any more. close OUTFH; }

Then your_function() just relies on its caller to do the right thing. If you want to pass your_function() a filename to take as output, then you'd call it as you'd expect:

your_function( $string, \*INPUT, '/tmp/somefile' );

On the other hand, if you want to pass your_function() an already opened filehandle, and use that for output, then you'd call it as:

# print to STDOUT instead of to disk your_function( $string, \*INPUT, "&STDOUT" ); # print to already-opened filehandle open OUTPUT, '> /tmp/somefile' or die "/tmp/somefile: $!\n"; your_function( $string, \*INPUT, "&OUTPUT" );

For more info on this, check out Obscure Open Tricks in perlopentut. There's a recommendation in there that you qualify the package name where OUTPUT is located, which I've ommitted in the code above.

One thing worth noting is that the line

open OUTFH, ">$out" or die "$out: $!\n";

Must appear as written (i.e. with no spaces between the > and $out). Avoid these following variations, since they don't do the same thing as the line above

# wrong: given, eg, &STDOUT, creates a file named '&STDOUT' open OUTFH, "> $out" or die "$out: $!\n"; # wrong: also creates, eg, '&STDOUT' open OUTFH, '>', $out or die "$out: $!\n";