为什么perl eval上的输出在公共bash输出和重定向STDOUT + STDERR到文件之间有所不同?

时间:2015-04-13 07:59:22

标签: bash perl

我的代码是:

  perl -e'
  use strict; use warnings;

  my $a={};

  eval{ test(); };

  sub test{
     print "11\n";
     if( $a->{aa} eq "aa"){
        print "aa\n";
     }
     else{
        print "bb\n";
     }
  }'

终端输出为:

  11
  Use of uninitialized value in string eq at -e line 9.
  bb

如果我在文件中重定向,则输出顺序不同。为什么呢?

  perl -e'
  ...
  ' > t.log 2>&1

cat t.log:

  Use of uninitialized value in string eq at -e line 9.
  11
  bb

我的perl版本:

  This is perl 5, version 18, subversion 4 (v5.18.4) built for x86_64-linux-thread-multi
  (with 20 registered patches, see perl -V for more detail)

2 个答案:

答案 0 :(得分:4)

更简单的问题演示:

$ perl -e'print("abc\n"); warn("def\n");'
abc
def

$ perl -e'print("abc\n"); warn("def\n");' 2>&1 | cat
def
abc

这是由于STDOUT和STDERR的缓冲方式不同。

  • STDERR未缓冲。
  • 如果STDOUT连接到终端,当遇到换行符时,STDOUT会刷新其缓冲区。
  • STDOUT在缓冲区已满时刷新缓冲区。

$| = 1;关闭STDOUT [1] 的缓冲。

$ perl -e'$| = 1; print("abc\n"); warn("def\n");' 2>&1 | cat
abc
def

  1. 实际上,当前select ed句柄是print写入的句柄,如果没有指定句柄,则默认为STDOUT。

答案 1 :(得分:0)

这只是一个autoflush问题NO eval问题。

解决方案是:

perl -e'
use strict; 
use warnings;

$|++; # <== this autoflush print output

my $a={};
test();

sub test{ 
   print "11\n";
   if( $a->{aa} eq "aa"){
      print "aa\n";
   }
   else{
      print "bb\n";
   }
}' > t.log 2>&1

在终端上的某些情况下是同样的问题:

perl -e'print(“abc”); print(STDERR“def \ n”);打印( “GHI \ n”);'

获得正确订单的唯一方法是打开autoflush!

@dgw + ikegami ==&gt;感谢的

相关问题