si28719e
si28719e

Reputation: 2165

Is it possible to open a pipe-based filehandle which prints to a variable in perl?

I know I can do this,


------
open(F,">",\$var);
print F "something cool";
close(F);
print $var;
------

or this,

 

open(F, "| ./prog1 | ./prog2 > tmp.file");
print F "something cool";
close(F);

but is it possible to combine these? The semantics of what I'd like to do should be clear from the following,


open(F,"|./prog1 | ./prog2", \$var);
print F "something cool";
close(F);
print $var;

however the above clearly won't work.

A few minutes of experimenting and googling seems to indicate that this is not possible, but I'd like to know if I'm stuck with using the `` to capture the output.

Upvotes: 2

Views: 343

Answers (5)

si28719e
si28719e

Reputation: 2165

What I actually wanted to do is not possible in perl.

Upvotes: 0

daotoad
daotoad

Reputation: 27183

You can achieve your goal a couple of ways. None of them quite as easy as piling extra stuff into open.

You can use IO::Tee or other similar module, or even write your own tee style subroutine:

my $var ='';

open my $vh, '>', \$var or die "oh noes $!\n";
open my $ph, '| ./prog1 | ./prog2' or die "Uh oh $!\n";

my @handles = ($vh, $ph);

print_to_all( \@handles,
    "I like cheese.\n",
    "I like teas.\n",
);

print $var;    

sub print_to_all {
     my $handles = shift;

     for my $h ( @$handles ) {
         print $h @_;
     }

     return;
}

Another way to go would be to make a tied variable that acts as a file handle and a scalar at the same time.

Upvotes: 1

edgar.holleis
edgar.holleis

Reputation: 4991

  • IPC::Open2 might do the trick, see man perlipc. More likely than not, however, you will deadlock your program that way. It's safe though, as long as the data in the pipe is smaller than PIPE_BUF (on Linux 4096), only written once, and the write-side immediately closed after writing the data and before reading the result.

  • You might try to rewrite your program to fork such that you end up with: YourProg | ./prog1 | ./prog2 | YourProgForked.

  • On modern Linux you can use /dev/shm to host a temporary file entirely in virtual memory.

Upvotes: 0

si28719e
si28719e

Reputation: 2165

It seems that this is not possible as perl does not support 'pipe at both ends'. More info here,

http://perldoc.perl.org/perlipc.html

Corion over at perlmonks.org answered this for me.

Upvotes: 0

Robert Massaioli
Robert Massaioli

Reputation: 13477

What you want to do is open the file handle as you have, read the contents to a variable, append whatever you want to that variable and then set the environment variable as is stated here to the full string that you have just generated.

You were almost there and I hope that helps. :)

Upvotes: 0

Related Questions