Perl has lots of handy idioms for doing common things easily, including:
The file-reading operator <HANDLE>
, if used without a filehandle, will seamlessly open and read all files in @ARGV
, one line at a time:
while (<>) { print $., $_; }
By (locally) resetting the input record separator $/
, I can "slurp" a whole file at once:
local $/; $content = <HANDLE>;
But these two idioms don't work quite work together as I expected: After I reset $/
, slurping with <>
stops at end of file: The following gives me the contents of the first file only.
local $/; $content = <>;
Now, I trust that this behavior must be by design, but I don't really care. What's the concise Perl idiom for fetching all content of all files into a string? (This related question mentions a way to slurp a list of files into separate strings, which is a start... but not terribly elegant if you still need to join the strings afterwards.)
There are several ways in Perl to read an entire file into a string, (a procedure also known as “slurping”). If you have access to CPAN, you can use the File::Slurp module: use File::Slurp; my $file_content = read_file('text_document. txt');
There is a strange scalar variable called $_ in Perl, which is the default variable, or in other words the topic. In Perl, several functions and operators use this variable as a default, in case no parameter is explicitly used.
If your program is slurping that means it's not working with the data as it becomes available and rather makes you wait for however long it might take for the input to complete.
You realise that you are only hiding multiple open
calls, right? There's no magic way to read multiple files without opening all of them one by one
As you have found, Perl will stop reading at the end of each file if $/
is set to undef
The internal mechanism that handles <>
removes each file name from @ARGV
as it is opened, so I suggest that you simply use a while
loop that reads using <>
until @ARGV
is empty
It would look like this
use strict;
use warnings 'all';
my $data;
{
local $/;
$data .= <> while @ARGV;
}
Since there doesn't seem to be a way to slurp everything at once, one compact solution would be to place <>
in list context. The implicit repeated calls will fetch everything.
local $/;
$data = join "", <>;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With