【问题标题】:perl how to capture STDOUT of list form system call as a filehandleperl如何将列表表单系统调用的STDOUT捕获为文件句柄
【发布时间】:2025-12-02 05:20:10
【问题描述】:

以下原型演示了如何将“boss”脚本调用的“worker”脚本的STDOUT 捕获为FILEHANDLE,并将FILEHANDLE 的内容转换为可以操作的数组在“老板”脚本中。老板脚本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;

还有“工人”junk2.pl

#!/usr/bin/perl
use strict; use warnings; use 5.18.2;
print "$0";

如果$worker 不需要其元素包含空格的数组作为参数,则使用open 和定义FILEHANDLE 是可以的。但是如果需要这样一个复杂的参数,就必须以列表的形式调用“worker”脚本,就像在“boss”脚本的底部一样。 “列表形式”见Calling a shell command with multiple arguments

在这种情况下,如何将STDOUT 捕获为FILEHANDLE?如何修改“boss”脚本的底线来完成这个?

【问题讨论】:

    标签: list perl filehandle


    【解决方案1】:

    还有一种更简单的方法,就是使用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;
    

    【讨论】:

      【解决方案2】:

      您可以继续使用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;
      

      警告:如果@args 为空,则上面会将$prog 的值视为shell 命令。

      这里也可以使用通用的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);
      

      还有Capture::Tiny,它提供了用于捕获 STDOUT 和 STDERR 的简约界面。


      请注意,您可以使用String::ShellQuoteshell_quotesh 构建命令。

      use String::ShellQuote qw( shell_quote );
      
      my $cmd = shell_quote("junk2.pl", @array);
      

      【讨论】:

        最近更新 更多