Leer datos sin búfer de la tubería en Perl

Estoy tratando de leer datos sin búfer de una tubería en Perl. Por ejemplo en el siguiente programa:

open FILE,"-|","iostat -dx 10 5";
$old=select FILE;
$|=1;
select $old;
$|=1;

foreach $i (<FILE>) {
  print "GOT: $i\n";
}

iostat escupe datos cada 10 segundos (cinco veces). Usted esperaría que este programa hiciera lo mismo. Sin embargo, parece colgar durante 50 segundos (es decir, 10x5), después de lo cual escupe todos los datos.

¿Cómo puedo hacer que devuelva los datos disponibles (sin búfer), sin esperar hasta EOF?

PD: he visto numerosas referencias a esto en Windows; lo estoy haciendo en Linux.

preguntado el 09 de marzo de 12 a las 15:03

Deberías estar usando while no es un foreach. Y su almacenamiento en búfer de salida es irrelevante, dado que es un identificador de entrada, no un identificador de salida. -

¿Cuál es la diferencia al usar while y foreach? -

@alertjean: En foreach my $i (<FILE>) { ... }, la lectura del archivo se realiza en contexto de lista, es decir, se lee todo el archivo antes de que las líneas se procesen en el foreach lazo. En while (my $i = <FILE>) { ... }, la lectura se realiza en contexto escalar, es decir, cada línea se lee y luego se procesa en el bloque while, antes de que se lea la siguiente línea. -

4 Respuestas

#!/usr/bin/env perl

use strict;
use warnings;



open(PIPE, "iostat -dx 10 1 |")       || die "couldn't start pipe: $!";

while (my $line = <PIPE>) {
    print "Got line number $. from pipe: $line";
}

close(PIPE)                           || die "couldn't close pipe: $! $?";

respondido 12 mar '12, 19:03

Si está bien esperar en su secuencia de comandos de Perl en lugar del comando de Linux, esto debería funcionar. No creo que Linux devuelva el control al script de Perl antes de que se complete la ejecución del comando.

#!/usr/bin/perl -w
my $j=0;
while($j!=5)
{
    open FILE,"-|","iostat -dx 10 1";
    $old=select FILE;
    $|=1;
    select $old;
    $|=1;

    foreach $i (<FILE>)
    {
        print "GOT: $i";
    }
    $j++;
    sleep(5);
}

respondido 09 mar '12, 17:03

Ubicación. $| solo afecta al búfer de salida. No puede afectar el almacenamiento en búfer de salida del otro programa de esa manera. Además, ¿qué pasa con el extraño abierto en lugar de solo open(PIPEHANDLE, "iostat -dx 10 1 |") || die "can't start pipe";? Nunca podré recordar "|-" vs "-|" yo mismo. De todos modos, si el iostat El programa no está descargando sus búferes en una tubería, debe recurrir a ptys, lo cual es una verdadera molestia pero inevitable. - cristo

Tengo el siguiente código que funciona para mí

#!/usr/bin/perl
use strict;
use warnings;
open FILE,"-|","iostat -dx 10 5";

while (my $old=<FILE>)
{
  print "GOT: $old\n";
}

respondido 09 mar '12, 17:03

Por qué no open(FILE, "iostat -dx 10 5 |") ? - cristo

@tchist porque open PIPE, '-|', 'iostat', '-dx', 10, 5 o morir $! - larelogio

Hasta ahora, las soluciones no me funcionaron con respecto a la eliminación del búfer (Windows ActiveState Perl 5.10).

Según http://perldoc.perl.org/PerlIO.html, "Para obtener una secuencia sin búfer, especifique una capa sin búfer (por ejemplo: unix) en la llamada abierta:".

So

open(PIPE, '-|:unix', 'iostat -dx 10 1') or die "couldn't start pipe: $!";

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

close(PIPE);

que funcionó en mi caso.

Respondido 08 Feb 13, 20:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.