2012-06-21 13 views
15

Perl ofrece esta característica muy agradable:Perl: ¿Cómo obtener un nombre de archivo cuando se utiliza <> construir?

while (<>) 
{ 
    # do something 
} 

... que permite que la secuencia de comandos para ser utilizado como script.pl <filename>, así como cat <filename> | script.pl.

Ahora, ¿hay alguna forma de determinar si el script se ha llamado de la manera anterior y, en caso afirmativo, cuál era el nombre del archivo?

Sé que lo sabía una vez, y sé que incluso usé el constructo, pero no recuerdo dónde ni cómo. Y resultó muy difícil buscar en la red para esto ("perl stdin filename"? No ...).

Ayuda, por favor?

+2

¿Puedes hacerlo marcando @ARGV? – beresfordt

+1

Perdón por el anterior/último, lo que parece haber causado cierta confusión. – DevSolar

+1

Puede encontrar la mayoría de las cosas en la documentación. 'perldoc perlvar' contiene información sobre' $ ARGV', por ejemplo. – TLP

Respuesta

20

La variable $ARGV contiene el archivo actual que se está procesando.

$ echo hello1 > file1 
$ echo hello2 > file2 
$ echo hello3 > file3 
$ perl -e 'while(<>){s/^/$ARGV:/; print;}' file* 
file1:hello1 
file2:hello2 
file3:hello3 
+1

@Quentin: aún así, es la única parte de la pregunta que es realmente posible. – lanzz

+1

"que permite que el script se use como' script.pl filename' "..." Ahora, hay una forma de determinar si el script se ha llamado de la manera anterior "=> former way =>' script.pl filename' –

+1

... pero es la respuesta correcta, como lo demostró una prueba rápida. Una segunda prueba mostró que '$ ARGV' contiene' -' si se alimenta de una tubería. – DevSolar

2

si es que quiere saber acerca de cuando <> cambia a un nuevo archivo (por ejemplo, en mi caso - que quería grabar el nuevo nombre de archivo y número de línea), entonces el eof() function documentation ofrece un truco:

# reset line numbering on each input file 
while (<>) { 
    next if /^\s*#/; # skip comments 
    print "$.\t$_"; 
} continue { 
    close ARGV if eof; # Not eof()! 
} 
+0

¡Agradable! No realmente en el tema, pero agradable de todos modos. – DevSolar

3

El I/O Operators section of perlop es muy informativo sobre esto.

Esencialmente, la primera vez que se ejecuta <>, - se agrega a @ARGV si comenzó vacío. La apertura - tiene el efecto de clonar el identificador de archivo STDIN, y la variable $ARGV se establece en el elemento actual de @ARGV a medida que se procesa.

Aquí está el clip completo.

El gestor de archivo nulo "<>" es especial: se puede utilizar para emular el comportamiento de sed y awk, y cualquier otro programa de filtro Unix que toma una lista de nombres de archivo , haciendo lo mismo a cada línea de entrada de todos ellos. La entrada de "<>" proviene de la entrada estándar o de cada archivo que figura en la línea de comandos. Así es como funciona: se evalúa la primera vez "<>", se comprueba la matriz @ARGV, y si está vacía, $ ARGV [0] se establece en "-", que cuando se abre proporciona una entrada estándar. La matriz @ARGV se procesa como una lista de nombres de archivos. El bucle

while (<>) { 
     ...      # code for each line 
    } 

es equivalente a la siguiente pseudo código Perl como:

unshift(@ARGV, '-') unless @ARGV; 
    while ($ARGV = shift) { 
     open(ARGV, $ARGV); 
     while (<ARGV>) { 
      ...   # code for each line 
     } 
    } 

excepto que no es tan engorroso que decir, y realmente funciona. Es realmente cambia la matriz @ARGV y pone el nombre de archivo actual en la variable $ ARGV. También utiliza filehandle ARGV internamente. "<>" es solo sinónimo de "< ARGV>", que es mágico. (El pseudo código anterior no funciona porque trata "< ARGV>" como no mágico.)

Cuestiones relacionadas