Perl Language
Leyendo el contenido de un archivo en una variable
Buscar..
La forma manual
open my $fh, '<', $filename
or die "Could not open $filename for reading: $!";
my $contents = do { local $/; <$fh> };
Después de abrir el archivo (lea man perlio
si desea leer codificaciones de archivo específicas en lugar de bytes sin procesar), el truco está en el bloque do
: <$fh>
, el identificador de archivo en un operador de diamante, devuelve un solo registro del archivo . La variable "separador de registro de entrada" $/
especifica qué es un "registro"; de forma predeterminada, se establece en un carácter de nueva línea, por lo que "un registro" significa "una sola línea". Como $/
es una variable global, local
hace dos cosas: crea una copia local temporal de $/
que desaparecerá al final del bloque y le otorga el valor (no-) undef
(el "valor" que Perl da a variables sin inicializar). Cuando el separador de registro de entrada tiene ese (no) valor, el operador de diamante devolverá el archivo completo. (Considera que todo el archivo es una sola línea).
Usando do
, incluso puede moverse manualmente abriendo un archivo. Para la lectura repetida de archivos,
sub readfile { do { local(@ARGV,$/) = $_[0]; <> } }
my $content = readfile($filename);
puede ser usado. Aquí, otra variable global ( @ARGV
) se localiza para simular el mismo proceso utilizado al iniciar un script perl con parámetros. $/
sigue siendo undef
, ya que la matriz que está frente a él "come" todos los argumentos entrantes. A continuación, el operador Diamond <>
nuevamente entrega un registro definido por $/
(el archivo completo) y regresa del bloque do
, que a su vez regresa del sub.
El sub no tiene un manejo explícito de errores, lo cual es una mala práctica. Si se produce un error al leer el archivo, recibirá undef
como valor de retorno, en lugar de una cadena vacía de un archivo vacío.
Otra desventaja del último código es el hecho de que no puede usar PerlIO para diferentes codificaciones de archivos: siempre obtiene bytes sin procesar.
Camino :: Diminuto
Usar el idioma de The Manual Way varias veces en una secuencia de comandos pronto se vuelve tedioso, por lo que es posible que desee probar un módulo.
use Path::Tiny;
my $contents = path($filename)->slurp;
Puede pasar una opción binmode
si necesita control sobre las codificaciones de archivos, finales de línea, etc. - vea man perlio
:
my $contents = path($filename)->slurp( {binmode => ":encoding(UTF-8)"} );
Path::Tiny
también tiene muchas otras funciones para tratar con archivos, por lo que puede ser una buena opción.
Archivo :: Slurper
Este es un módulo minimalista que solo absorbe archivos en variables, nada más.
use File::Slurper 'read_text';
my $contents = read_text($filename);
read_text()
toma dos parámetros opcionales para especificar la codificación del archivo y si los finales de línea deben traducirse entre los estándares LF de Unixish o CRLF de DOSish:
my $contents = read_text($filename, 'UTF-8', 1);
Archivo :: Slurp
No lo uses Aunque ha existido durante mucho tiempo y sigue siendo el módulo que la mayoría de los programadores sugerirán, está roto y no es probable que se solucione .
Slurping un archivo en una variable de matriz
open(my $fh, '<', "/some/path") or die $!;
my @ary = <$fh>;
Cuando se evalúa en el contexto de la lista, el operador de diamante devuelve una lista que consta de todas las líneas del archivo (en este caso, asignando el resultado a un contexto de lista de suministros de matriz). El terminador de línea se conserva, y se puede eliminar mediante la masticación:
chomp(@ary); #removes line terminators from all the array elements.
Archivo de slurp en una sola línea
El separador de registro de entrada se puede especificar con el interruptor -0
( cero , no mayúscula ). Toma un número octal o hexadecimal como valor. Cualquier valor de 0400
o superior hará que Perl absorba los archivos, pero por convención, el valor utilizado para este propósito es 0777
.
perl -0777 -e 'my $file = <>; print length($file)' input.txt
Yendo más allá con el minimalismo, al especificar -n
modificador hace que Perl lea automáticamente cada línea (en nuestro caso, el archivo completo) en la variable $_
.
perl -0777 -ne 'print length($_)' input.txt