in reply to Re^2: putting text into array word by word
in thread putting text into array word by word
The only thing I used that could be accused of being slightly obscure is:
do { local $/ = <$infile> }This is a fairly commonly used idiom for reading an entire file into a single string, but exactly how it works is somewhat obscure.
Firstly, when you call <$filehandle>, Perl reads a single line from the file $filehandle. See perldoc -f readline
Secondly, the variable $/ is used by Perl's file reading function to indicate what character to use as a line terminator (technically it's called the record separator). So normally, $/ is set to "\n". If you set $/ to undef, then Perl won't treat any characters as line terminators, so the readline function will simply read the entire remainder of the file. See perldoc -f readline and perldoc perlvar
So, just based on the above knowledge, we can slurp the entire contents of a filehandle into a string like this:
$/ = undef; my $string = <$filehandle>;
But actually, what if other parts of our code rely on $/ being set to "\n"? We don't want to permanently undefine it.
my $old_terminator = $/; $/ = undef; my $string = <$filehandle>; $/ = $old_terminator;
Because temporarily changing the value of a variable is such a common need, Perl provides a shortcut. The local keyword allows you to set a new temporary value for a variable for a particular code block, such that the variable's old value will be automatically restored at the end of the block. See perldoc -f local. So our code becomes:
my $string; { local $/ = undef; $string = <$filehandle>; }
But = undef is redundant because all newly declared scalar variables (including local ones) are undefined. So now we have:
my $string; { local $/; $string = <$filehandle>; }
Now, the do block allows Perl to run a block of code and return the result of the last statement. See perlsyn. So our code can become:
my $string = do { local $/; <$filehandle>; }
The last simplification relies on the fact that in the following statement:
local $/ = <$filehandle>
Perl does things in this order:
Thus we end up with the situation where you can read the entire contents of an open file handle into a string using:
my $string = do { local $/ = <$infile> };Now, of course I could have included the entire explanation above as a comment, but I try to stick to a policy of never writing comments which are longer than the code itself.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^4: putting text into array word by word
by jms53 (Monk) on Jan 10, 2012 at 19:46 UTC |