代码之家  ›  专栏  ›  技术社区  ›  Uri London

当Perl管道可用时,如何从它获得输出?

  •  7
  • Uri London  · 技术社区  · 16 年前

    以下代码工作正常:

    open( PIPE, '-|', 'ant' );
    for( <PIPE> ) {
        print;
    }
    

    但是,它不能满足我的需要。由于Ant构建可能需要5分钟,所以我想逐行查看输出。 相反,我在流程的最后得到了整个输入。

    通过Perl调试器查看它,Perl会等待“for”语句,直到Ant终止。为什么会这样?

    3 回复  |  直到 16 年前
        1
  •  8
  •   Community Mohan Dere    9 年前

    就完整性而言(问题已解决,正如对URI答案的注释所指出的那样),出现问题的原因是 for 表达式计算 <> 列表上下文中的运算符( see ,相当于:

    foreach $line (@lines = <PIPE>) {
        print $line;
    }
    

    在列表上下文中, <> 操作员试图读取 全部的 从它的输入到列表的行-输入来自一个进程,它将阻塞直到进程结束。只有在这之后,它才会进入循环体。

    替代语法

    while( <PIPE> ) {           
        print; 
    } 
    

    等价于

    while(  $line = <PIPE> ) {
        print $line;
    }
    

    也就是说,它消耗每个循环迭代中输入的每一行,这就是我们在这个场景中想要做的。

        2
  •  3
  •   nc3b    16 年前

    我认为这个问题正在缓和。你可以做文件句柄 热的 (未缓冲)如此:

    select PIPE;
    $| = 1; # the pipe is just a coincidence. that's the variable's name
    select STDOUT; # select it back
    

    这应该禁用管道缓冲。我在年读到过类似的东西 学习Perl,第5 . 见 this ,也。您可能还应该确保缓冲不会在其他地方发生。

    编辑:替换 对于 具有 虽然 解决了这个问题

    我想我现在明白了。 while 获取每一行并运行循环,而 for 行为像 foreach 第一 获取所有行(它需要列表上下文)和 然后 绕线。

        3
  •  2
  •   Uri London    16 年前

    找到它了。 “for”语句有问题。

    以下代码按预期工作

    open( PIPE, '-|', 'ant' ); 
    while( <PIPE> ) {           # replacing 'for' with 'while'
        print; 
    } 
    

    我不知道原因,但现在起作用了。