Reputation: 1306
The following prototypes demonstrate how one can capture the STDOUT
of a "worker" script, called by the "boss" script, as a FILEHANDLE
and turn the contents of FILEHANDLE
into an array that one can manipulate in the "boss" script. The boss script junk.pl
:
#!/usr/bin/perl
use strict; use warnings;
my $boppin;
my $worker = "junk2.pl";
open(FILEHANDLE, "$worker |");
my @scriptSTDOUT=<FILEHANDLE>;
close FILEHANDLE;
my $count=0;
foreach my $item ( @scriptSTDOUT ) {
$count++;
chomp $item;
print "$count\t$item\n";
}
if ( @scriptSTDOUT ) {
$boppin = pop @scriptSTDOUT; print "boppin=$boppin\n";
} else {
print STDERR "nothing returned by $worker\n";
}
my @array = ( '. . . \x09 wow\x21' , 5 );
system $worker, @array;
and the "worker" junk2.pl
:
#!/usr/bin/perl
use strict; use warnings; use 5.18.2;
print "$0";
This use of open
and definition of a FILEHANDLE
is okay if the $worker
does not require, as argument, an array whose elements contain whitespace. But if such a complex argument is required, one must call the "worker" script in list form, as at the bottom of the "boss" script. For "list form", see Calling a shell command with multiple arguments.
In that case, how does one capture the STDOUT
as a FILEHANDLE
? How can I modify the bottom line of the "boss" script to accomplish this?
Upvotes: 1
Views: 67
Reputation: 386361
You can continue to use open
as follows:
open(my $child, "-|", $prog, @args)
or die("Can't launch \"$prog\": $!\n");
my @lines = <$child>;
close($child);
die("$prog killed by signal ".( $? & 0x7F )."\n") if $? & 0x7F;
die("$prog exited with error ".( $? >> 8 )."\n") if $ ?>> 8;
Warning: The above will treat the value of $prog
as a shell command if @args
is empty.
General-purpose IPC::Run could also be used here.
use IPC::Run qw( run );
run [ $prog, @args ],
'>', \my $out;
die("$prog killed by signal ".( $? & 0x7F )."\n") if $? & 0x7F;
die("$prog exited with error ".( $? >> 8 )."\n") if $ ?>> 8;
my @lines = split(/^/m, $out);
There's also Capture::Tiny which offers a minimalist interface for capturing both STDOUT and STDERR.
Note that you can use String::ShellQuote's shell_quote
to build commands for sh
.
use String::ShellQuote qw( shell_quote );
my $cmd = shell_quote("junk2.pl", @array);
Upvotes: 2
Reputation: 365
There is a more simple approach and it is to use IPC::Run
using a simple code like this
use strict;
use warnings;
use IPC::Run qw(run);
my $in = ""; # some data you want to send to the sub-script, keep it empty if there is none
# the data will be received from the STDIN filehandle in the called program
my $out = ""; # variable that will hold data writed to STDOUT
my $err;
run ["perl", "junk2.pl"], \$in, \$out, \$err;
Upvotes: 2