下面的代码工作之类的罚款:如何从Perl管道获得输出?
open(PIPE, '-|', 'ant');
for(<PIPE>) {
print;
}
但是,它不会做我想做的。由于Ant构建可能需要5分钟,我希望逐行看到输出。 取而代之,我在整个过程结束时收到整个输入。
用Perl调试器查看它,Perl等待'for'语句,直到Ant终止。这是为什么?
下面的代码工作之类的罚款:如何从Perl管道获得输出?
open(PIPE, '-|', 'ant');
for(<PIPE>) {
print;
}
但是,它不会做我想做的。由于Ant构建可能需要5分钟,我希望逐行看到输出。 取而代之,我在整个过程结束时收到整个输入。
用Perl调试器查看它,Perl等待'for'语句,直到Ant终止。这是为什么?
只是为了完整性(问题解决了在以乌里的答复评论中指出)的问题出现,因为for
表达式的计算结果在列表环境中<>
运营商(see),等同于以下内容:
foreach $line (@lines = <PIPE>) {
print $line;
}
在列表上下文中,<>
操作员尝试从其输入读取所有行以指派给列表 - 并且输入来自进程,它将阻塞,直到进程结束。只有在之后它才会进入循环体。
替代语法
while(<PIPE>) {
print;
}
相当于而是
while( $line = <PIPE>) {
print $line;
}
即,它消耗在每次循环迭代输入中的每行,这是一个想在这种情况下该怎么办。
我相信问题是缓冲。你可以做出这样的文件句柄热(无缓冲),所以:
select PIPE;
$| = 1; # the pipe is just a coincidence. that's the variable's name
select STDOUT; # select it back
这应该PIPE禁用缓冲。我在学习Perl,5TH。另请参阅this。你也应该确保缓冲不会发生在其他地方。
编辑:OP张贴与而更换为解决了这个问题
我想我现在明白了。 while
获取每一行并运行循环,而for
作用就像foreach
和第一得到所有的行(它需要列表上下文)和然后环路上的行。
找到它。 问题在于'for'语句。
下面的代码按预期工作
open(PIPE, '-|', 'ant');
while(<PIPE>) { # replacing 'for' with 'while'
print;
}
我不知道原因,但现在它正在发挥作用。
要理解原因,请参阅http://stackoverflow.com/questions/585341/ – Joe 2010-05-23 21:15:23
如果您回答了自己的问题,最好编辑原始问题并添加答案,而不是发表回复。 – 2010-05-23 22:42:45
@Barry Brown发布你自己的答案,并接受它,如果没有人提供更好的答案被接受(heh)实践SO。 http://meta.stackexchange.com/questions/12513/stackoverflow-should-i-answer-my-own-question-or-not – hobbs 2010-05-24 01:16:41
缓冲可能是问题,但有问题的缓冲区在Ant方面,而不是Perl的方面。您只需要关闭输出管道而不是输入管道的缓冲。你需要找到一些方法告诉Ant不要缓存它的输出。你无法解决Perl方面的问题。 – cjm 2010-05-23 21:00:18