简体   繁体   English

perl 如何捕获列表表单系统调用的 STDOUT 作为文件句柄

[英]perl how to capture STDOUT of list form system call as a filehandle

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.下面的原型演示如何能够捕捉STDOUT一个“工人”剧本,由“老板”脚本调用,为FILEHANDLE ,把内容FILEHANDLE到一个数组中,人们可以在“老大”脚本操作。 The boss script junk.pl : boss脚本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 :和“工人” 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.如果$worker不需要其元素包含空格的数组作为参数,则使用open和定义FILEHANDLE是可以的。 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.但是,如果需要如此复杂的参数,则必须以列表形式调用“worker”脚本,如“boss”脚本的底部。 For "list form", see Calling a shell command with multiple arguments .对于“列表形式”,请参阅使用多个参数调用 shell 命令

In that case, how does one capture the STDOUT as a FILEHANDLE ?在这种情况下,如何将STDOUT捕获为FILEHANDLE How can I modify the bottom line of the "boss" script to accomplish this?如何修改“老板”脚本的底线来实现这一点?

There is a more simple approach and it is to use IPC::Run using a simple code like this有一种更简单的方法,它是使用IPC::Run使用像这样的简单代码

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;

You can continue to use open as follows:可以继续使用open如下:

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.警告:如果@args为空,上面将把$prog的值视为一个 shell 命令。

General-purpose IPC::Run could also be used here.通用IPC::Run也可以在这里使用。

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.还有Capture::Tiny ,它提供了一个用于捕获 STDOUT 和 STDERR 的极简界面。


Note that you can use String::ShellQuote 's shell_quote to build commands for sh .请注意,您可以使用String::ShellQuoteshell_quotesh构建命令。

use String::ShellQuote qw( shell_quote );

my $cmd = shell_quote("junk2.pl", @array);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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