phileas fogg
phileas fogg

Reputation: 1933

How can I slurp STDIN in Perl?

I piping the output of several scripts. One of these scripts outputs an entire HTML page that gets processed by my perl script. I want to be able to pull the whole 58K of text into the perl script (which will contain newlines, of course).

I thought this might work:

open(my $TTY, '<', '/dev/tty');

my $html_string= do { local( @ARGV, $/ ) = $TTY ; <> } ;

But it just isn't doing what I need. Any suggestions?

Upvotes: 18

Views: 16466

Answers (6)

brian d foy
brian d foy

Reputation: 132773

No one mentioned what you were doing wrong. Here's what you tried:

open(my $TTY, '<', '/dev/tty');

my $html_string= do { local( @ARGV, $/ ) = $TTY ; <> } ;

The @ARGV array is the list of command-line arguments, so they are simple strings. You don't put an open filehandle in there. You might be able to temporarily open ARGV, the variable with the same name but different type, then use <>, but that leads to insanity.

But, it sounds like you are just want whatever is standard input since you are piping output in, and Sinan already showed that (and you accepted his answer).

Upvotes: 0

Marnix A.  van Ammers
Marnix A. van Ammers

Reputation: 178

I've always used a bare block.

  my $x;
  {
    undef $/; # Set slurp mode
    $x = <>;  # Read in everything up to EOF
  }
  # $x should now contain all of STDIN

Upvotes: 0

mirabilos
mirabilos

Reputation: 5317

tl;dr: see at the bottom of the post. Explanation first.

practical example

I’ve just wondered about the same, but I wanted something suitable for a shell one-liner. Turns out this is (Korn shell, whole example, dissected below):

print -nr -- "$x" | perl -C7 -0777 -Mutf8 -MEncode -e "print encode('MIME-Q', 'Subject: ' . <>);"; print

Dissecting:

  • print -nr -- "$x" echos the whole of $x without any trailing newline (-n) or backslash escape (-r), POSIX equivalent: printf '%s' "$x"
  • -C7 sets stdin, stdout, and stderr into UTF-8 mode (you may or may not need it)
  • -0777 sets $/ so that Perl will slurp the entire file; reference: man perlrun(1)
  • -Mutf8 -MEncode loads two modules
  • the remainder is the Perl command itself: print encode('MIME-Q', 'Subject: ' . <>);, let’s look at it from inner to outer, right to left:
    • <> takes the entire stdin content
    • which is concatenated with the string "Subject: "
    • and passed to Encode::encode asking it to convert that to MIME Quoted-Printable
    • the result of which is printed on stdout (without any trailing newline)
  • this is followed by ; print, again in Korn shell, which is the same as ; echo in POSIX shell – just echoïng a newline.

tl;dr

Call perl with the -0777 option. Then, inside the script, <> will contain the entire stdin.

complete self-contained example

#!/usr/bin/perl -0777
my $x = <>;
print "Look ma, I got this: '$x'\n";

Upvotes: 4

G. Cito
G. Cito

Reputation: 6378

I can't let this opportunity to say how much I love IO::All pass without saying:

♥ ♥ __ "I really like IO::All ... a lot" __ ♥ ♥

Variation on the POD SYNOPSIS:

use IO::All;
my $contents < io('-') ;
print "\n printing your IO: \n $contents \n with IO::All goodness ..." ;

Warning: IO::All may begin replacing everything else you know about IO in perl with its own insidious goodness.

Upvotes: 8

Patrick Collins
Patrick Collins

Reputation: 4334

To get it into a single string you want:

#!/usr/bin/perl -w
use strict;

my $html_string;
while(<>){
   $html_string .= $_;
}

print $html_string;

Upvotes: 2

Sinan &#220;n&#252;r
Sinan &#220;n&#252;r

Reputation: 118118

my @lines = <STDIN>;

or

my $str = do { local $/; <STDIN> };

Upvotes: 59

Related Questions