¿Cómo puedo restablecer un identificador de archivo que recibe la entrada estándar en Perl?

StackOverflow https://stackoverflow.com/questions/1886103

  •  19-09-2019
  •  | 
  •  

Pregunta

Cuando emito un script Perl alguna entrada estándar, por ejemplo.

$ awk '{print $1"\t"$2}' foo.txt | myScript.pl

Tengo un script que contiene un error. Se lee la primera línea de entrada estándar, se pone algo de esa primera línea, y sólo analiza las líneas 2 a n de entrada estándar en lectura posterior:

open (FH, "< $input") or die $?;
my $firstLine = <FH>; // reads first line

...

while (my $line = <FH>) {
    // reads lines 2 through n
}
close (FH);

por lo que añade una declaración seek a este script para tratar de restablecer el identificador de archivo al principio del archivo:

use Fcntl qw(:seek);

...

open (FH, "< $input") or die $?;
my $firstLine = <FH>; // reads first line
seek (FH, 0, SEEK_SET) or die "error: could not reset file handle\n"; // should reset file handle

...

while (my $line = <FH>) {
    // reads lines 1 through n (in theory)
}
close (FH);

La adición de este comunicado seek trabaja para la entrada de archivos, pero no para la entrada estándar. El script se bloquea con el error:

 error: could not reset file handle 

¿Cómo puedo leer correctamente la primera línea de entrada estándar al comienzo de la secuencia de comandos, restablecer el identificador de archivo y después de leer todas las líneas 1 a N de la entrada estándar?

Creo que puedo escribir un caso especial para almacenar y procesar la primera línea antes del bucle while, pero estoy esperando que hay una solución a este problema más limpio que me permite manejar tanto la entrada estándar y archivo de entrada.

¿Fue útil?

Solución

Hay una manera fácil:

open (FH, "< $input") or die $?;
my $line = <FH>; // reads first line

//do stuff with first line

do {
    //stuff
} while ($line = <FH>);

Otros consejos

editar Reintegro de mi primer enfoque es que se debe cargar todas las líneas de FH en la memoria antes de procesar la lista. Este enfoque, por procedimiento abierto de Referencia de funciones escalares (disponible desde 5.8.0) no tendrá ese problema:

my $firstline = <FH>;
open(my $f1, '<', \$firstline);

...

while (my $line = <$f1> || <FH>) {
    # process line 1 through n
}

¿Qué hay de:

for my $line ($firstline, <FH>) {
    # process lines 1 through n
}

No creo que se pueda restablecer (o busco (0)) para STDIN. No es un identificador de archivo normal, como STDIN. Dado que no es en realidad un archivo, se requeriría que el STDIN hace buffering reajustable.

Creo que usted necesita para manejar la lectura y re-uso de la línea 1 de forma especial.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top