http://qs1969.pair.com?node_id=287647

Perl Idioms Explained - my $string = do { local $/; <FILEHANDLE> };

open FILEHANDLE, 'somefile.txt' or die $!; my $string = do { local $/; <FILEHANDLE> };

The above idiom is a consise way to "slurp" the entire contents of a file into a scalar without using a loop, such as:

open FILEHANDLE, 'somefile.txt' or die $!; my $string = ''; while (<FILEHANDLE>) { $string .= $_; }

How it works

The first piece of this code is the do "function", which returns the value of the last expression executed in it's block. In this case, that last expression is simply <FILEHANDLE>.

The expression <FILEHANDLE> will either return the next line from the filehandle if it is called in scalar context, or it will return the entire contents from the filehandle as a list if called in list context:

my $scalar = <FILEHANDLE>; # one line my @array = <FILEHANDLE>; # whole file

The reason why <FILEHANDLE> only returns one line is because by default, the built-in Perl variable $/ is set to one newline. $/ is the input record seperator, and it can be used to modify the behavior of how many records are read in when you use the diamond operators (<FILEHANDLE>). The docs explain that if $/ is set to undef, then accessing <FILEHANDLE> in scalar context will grab everything until the end of the file:

undef $/; my $scalar = <FILEHANDLE>; # whole file

However, changing Perl's built-in variables can be dangerous. Imagine you wrote a module that others use. Inside this module you set $/ to undef, thinking that everywhere else $/ will be the default value. Well, wrong. You just changed $/ for everyone that uses your module. This is one of those few places where local is the right choice.

Which brings us to the FIRST expression in our do block:

local $/;

This is the same thing as explicitly assigning $/ to undef:

local $/ = undef;

But not the same as:

$/ = undef; # Danger Will Robinson! Danger!

Because we are inside a do block when we use local, the value of $/ is temporarily changed, and we can rest assured that it will not affect code outside of our block (or scope). If we were not inside another block or scope, local $/ will only affect the package it was encountered in, but it's better to contain local $/ inside a temporay scope, unless you enjoy debugging hard to find bugs.


Summary

The do block is used create a temporary scope. Inside this temporary scope, we temporarily assign undef to $/ and retrieve the "next line" from our filehandle. Since $/ is undefined, this "next line" is "everything until End Of File" - hence, the entire file.


Caveats

Memory! Anytime you store an entire file you should be aware of it's potential size. If you only need to deal with one line at a time, then use a loop instead.

Also, a popular use for this idiom is in conjunction with the built-in DATA filehandle:

my $string = do {local $/;<DATA>};

This is handy for scripts that use modules such as Text::Template and HTML::Template, but note that both modules allow you to pass some kind of reference to a file handle, so this idiom is not needed. For example, instead of:

my $data = do {local $/;<DATA>}; my $template = HTML::Template->new(scalarref => \$data);

You can simply say:

my $template = HTML::Template->new(filehandle => \*DATA);

jeffa

L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)