简体   繁体   中英

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.

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.

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. :)

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.

  • 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 YourProg | ./prog1 | ./prog2 | YourProgForked YourProg | ./prog1 | ./prog2 | YourProgForked .

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

我实际上想做的事在perl中是不可能的。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM