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 .= $_; }
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.
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.
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)
|
---|