简体   繁体   中英

Perl IO::Pipe does not work within arrays

im trying the following:

I want to fork multiple processes and use multiple pipes (child -> parent) simultaneously. My approach is to use IO::Pipe.

#!/usr/bin/perl
use strict;
use IO::Pipe;
use LWP::UserAgent;

my $ua = LWP::UserAgent->new;
my @ua_processes = (0..9);
my $url = "http://<some-sample-textfile>";
my @ua_pipe;
my @ua_process;

$ua_pipe[0] = IO::Pipe->new();

$ua_process[0] = fork();
if( $ua_process[0] == 0 ) {
    my $response = $ua->get($url);
    $ua_pipe[0]->writer();
    print $ua_pipe[0] $response->decoded_content;
    exit 0;
}

$ua_pipe[0]->reader();
while (<$ua_pipe[0]>) {
    print $_;
}

In future i want to use multiple "$ua_process"s in an array.

After execution i got the following errors:

Scalar found where operator expected at ./forked.pl line 18, near "] $response"
        (Missing operator before  $response?)
syntax error at ./forked.pl line 18, near "] $response"
BEGIN not safe after errors--compilation aborted at ./forked.pl line 23.

If i dont use arrays, the same code works perfectly. It seems only the $ua_pipe[0] dont work as expected (together with a array).

I really dont know why. Anyone knows a solution? Help would be very appreciated!

Your problem is here:

print $ua_pipe[0] $response->decoded_content;

The print and say builtins use the indirect syntax to specify the file handle. This allows only for a single scalar variable or a bareword:

print STDOUT "foo";

or

print $file "foo";

If you want to specify the file handle via a more complex expression, you have to enclose that expression in curlies; this is called a dative block :

print { $ua_pipe[0] } $response-decoded_content;

This should now work fine.


Edit

I overlooked the <$ua_pipe[0]> . The readline operator <> also doubles as the glob operator (ie does shell expansion for patterns like *.txt ). Here, the same rules as for say and print apply: It'll only use the file handle if it is a bareword or a simple scalar variable. Otherwise, it will be interpreted as a glob pattern (implying stringification of the argument). To disambiguate:

  • For the readline <> , we have to resort to the readline builtin:

     while (readline $ua_pipe[0]) { ... } 
  • To force globbing <> , pass it a string: <"some*.pattern"> , or preferably use the glob builtin.

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