perl - “tee”qx运算符

时间:2011-02-17 17:27:39

标签: perl redirect

我正在编写一个目前有以下内容的脚本:

my @files = `$some_command`;
print @files;
chomp @files;
foreach my $file (@files)
{
    process($file);
}

它可以正常工作,但some_command部分占用了脚本的大部分时间。在此期间,stdout上没有任何内容,因为Perl已将some_command的输出重定向到填充@files数组。它仅在some_command完成后打印,Perl移至print @files;

是否有一些聪明的方法来更改此代码,以便some_command的输出在执行时出现?我可以使用tee(1)尝试这样的事情:

my $tmpfile = File::Temp->new();
system("$some_command | tee " . $tmpfile->filename);
my @files;
{ local $/ = undef; @files = split /\s/, <$tmpfile>; }

但如果有更简单的解决方案,我宁愿避免使用临时文件。

5 个答案:

答案 0 :(得分:5)

您可以打开手柄并在打印线条时自己手动填充阵列。

这样的事可能会奏效,

  open my $fh, '-|', $some_command;
  while(<$fh>)
  {
    print $_;
    push @files, $_;
  }
  close $fh;

答案 1 :(得分:2)

您可以跳过qx()运算符并直接打开进程输出流的文件句柄。此代码在功能上等同于my @files = qx($some_command)

 my @files = ();
 open my $proc_fh, "$some_command |";
 while (<$proc_fh>) {
     push @files, $_;
 }
 close $proc_fh;

但在while循环中,您可以使用$_执行任何操作:

 while (<$proc_fh>) {
     print "INPUT: $_\n";
     push @files, $_;
 }

一个重要的考虑因素是$some_command的输出缓冲行为。如果该命令缓冲其输出,那么在有大量数据可用之前,$proc_fh句柄将不会收到任何输入。

答案 2 :(得分:1)

File::Tee模块看起来可以做你想要的。有些例子在运行system()时重定向STDOUT。我没有用它,所以我不能给出更具体的例子,但看起来这对你来说是一个很好的起点。

答案 3 :(得分:1)

您还可以将命令作为文件描述符打开,并在命令生成时读取输出。这样的事情(取自http://www.netadmintools.com/art269.html):

#!/usr/bin/perl
open (PINGTEST, "/bin/ping  -c 5 netadmintools.com |");
$i=1;
while (<PINGTEST>){
print "Line # ".$i." ".$_;
$i++;
}
print "All done!\n";
close PINGTEST;

答案 4 :(得分:1)

Capture::Tiny可能就是你想要的。

   use Capture::Tiny qw/ tee tee_merged /;

   ($stdout, $stderr) = tee {
     # your code here
   };

   $merged = tee_merged {
     # your code here
   };