strawberry - perl tutorial
Perl: ¿Cómo obtener el nombre de archivo cuando se usa<> construir? (3)
Perl ofrece esta característica muy agradable:
while ( <> )
{
# do something
}
... que permite que el script se use como script.pl <filename>
así como cat <filename> | script.pl
cat <filename> | script.pl
.
Ahora, ¿hay una manera de determinar si el script ha sido llamado de la forma anterior, y si es así, cuál fue el nombre del archivo?
Sé que lo supe una vez, y sé que incluso utilicé el constructo, pero no puedo recordar dónde / cómo. Y resultó muy difícil buscar en la red para esto ("perl stdin filename"? No ...).
¿Ayuda por favor?
La sección Operadores de E / S de perlop
es muy informativa sobre esto.
Esencialmente, la primera vez que se ejecuta <>
, -
se agrega a @ARGV
si comenzó vacío. Apertura -
tiene el efecto de clonar el identificador del archivo STDIN
y la variable $ARGV
se establece en el elemento actual de @ARGV
medida que se procesa.
Aquí está el clip completo.
El identificador de archivo nulo "<>" es especial: puede usarse para emular el comportamiento de sed y awk, y cualquier otro programa de filtro de Unix que tome una lista de nombres de archivos, haciendo lo mismo con cada línea de entrada de todos ellos. La entrada de "<>" proviene de la entrada estándar o de cada archivo listado en la línea de comando. Así es como funciona: la primera vez que se evalúa "<>", se comprueba la matriz @ARGV y, si está vacía, $ ARGV [0] se establece en "-", que cuando se abre le da una entrada estándar. La matriz @ARGV se procesa como una lista de nombres de archivos. El lazo
while (<>) { ... # code for each line }
es equivalente al siguiente pseudo código similar a Perl:
unshift(@ARGV, ''-'') unless @ARGV; while ($ARGV = shift) { open(ARGV, $ARGV); while (<ARGV>) { ... # code for each line } }
excepto que no es tan engorroso decirlo, y realmente funcionará. Realmente cambia la matriz @ARGV y coloca el nombre de archivo actual en la variable $ ARGV. También utiliza filehandle ARGV internamente. "<>" es solo un sinónimo de "<ARGV>", que es mágico. (El pseudo código anterior no funciona porque trata "<ARGV>" como no mágico.)
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
Si le interesa saber cuándo <>
cambia a un nuevo archivo (por ejemplo, en mi caso, quería registrar el nuevo nombre de archivo y número de línea), entonces la documentación de la función eof () 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()!
}