以下代码工作正常:
open( PIPE, '-|', 'ant' );
for( <PIPE> ) {
print;
}
然而,它没有做我想要的。由于Ant构建可能需要5分钟,我希望逐行看到输出。 相反,我在整个过程结束时得到了整个输入。
使用Perl调试器查看它,Perl等待'for'语句,直到Ant终止。那是为什么?
答案 0 :(得分:8)
只是为了完整性(问题在Uri的回答评论中得到解决)问题出现了,因为for
表达式评估列表上下文中的<>
运算符(see),等效于以下内容:
foreach $line (@lines = <PIPE>) {
print $line;
}
在列表上下文中,<>
运算符尝试从其输入读取所有行以指向列表 - 并且输入来自进程,它将阻塞直到进程结束。只有在它之后它才会进入循环体。
替代语法
while( <PIPE> ) {
print;
}
等同于
while( $line = <PIPE> ) {
print $line;
}
,即它在每次循环迭代中消耗输入中的每一行,这就是在这种情况下想要做的事情。
答案 1 :(得分:3)
我认为问题在于缓冲。您可以像这样使文件句柄 hot (无缓冲):
select PIPE;
$| = 1; # the pipe is just a coincidence. that's the variable's name
select STDOUT; # select it back
这应禁用PIPE的缓冲。我在 Learning Perl,5TH 中读到了类似的内容。另见this。您可能还应该确保缓冲不会发生在其他地方。
编辑:OP发布用替换 解决问题
我想我现在明白了。 while
获取每一行并运行循环,而for
的行为类似于foreach
而首先获取所有行(它需要列表上下文)和然后循环遍布。
答案 2 :(得分:2)
找到它。 问题在于'for'语句。
以下代码按预期工作
open( PIPE, '-|', 'ant' );
while( <PIPE> ) { # replacing 'for' with 'while'
print;
}
我不知道原因,但现在它正在发挥作用。