我的代码是:
perl -e'
use strict; use warnings;
my $a={};
eval{ test(); };
sub test{
print "11n";
if( $a->{aa} eq "aa"){
print "aan";
}
else{
print "bbn";
}
}'
终端上的输出为:
11
Use of uninitialized value in string eq at -e line 9.
bb
如果我在文件中重定向,输出顺序会有所不同。为什么?
perl -e'
...
' > t.log 2>&1
猫 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)
问题的更简单演示:
$ perl -e'print("abcn"); warn("defn");'
abc
def
$ perl -e'print("abcn"); warn("defn");' 2>&1 | cat
def
abc
这是由于 STDOUT 和 STDERR 缓冲方式的差异。
- STDERR 未缓冲。
- 如果 STDOUT 连接到终端,则在遇到换行符时刷新其缓冲区。
- 否则,STDOUT 会在缓冲区已满时刷新其缓冲区。
$| = 1;
关闭了 STDOUT 的缓冲[1]。
$ perl -e'$| = 1; print("abcn"); warn("defn");' 2>&1 | cat
abc
def
- 实际上,当前
select
的 ed 句柄,如果未指定句柄,则print
写入该句柄,默认情况下为 STDOUT。
这只是
一个自动刷新问题,没有评估问题。
解决方案是:
perl -e'
use strict;
use warnings;
$|++; # <== this autoflush print output
my $a={};
test();
sub test{
print "11n";
if( $a->{aa} eq "aa"){
print "aan";
}
else{
print "bbn";
}
}' > t.log 2>&1
在某些情况下,终端上是相同的问题:
perl -e'print("abc"); print(STDERR "def"); print("ghi");'
获得正确顺序的唯一保存方法是打开自动刷新!
@dgw+池上==>谢谢