Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Perl, how do I "slurp" the contents of several files into a string?

Tags:

perl

Perl has lots of handy idioms for doing common things easily, including:

  1. 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 $., $_;  }
    
  2. 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.)

like image 540
alexis Avatar asked Jul 04 '16 10:07

alexis


People also ask

How do I slurp a file in Perl?

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');

What does $_ mean in Perl?

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.

What does it mean to slurp a file?

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.


2 Answers

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;
}
like image 126
Borodin Avatar answered Oct 04 '22 03:10

Borodin


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 "", <>;
like image 20
alexis Avatar answered Oct 04 '22 01:10

alexis