¿Cómo lee Perl en los archivos, cómo le indica que avance a la siguiente línea en el archivo de texto y cómo lo hace leer todas las líneas en el archivo .txt hasta, por ejemplo, alcanza el elemento "plátano"?Lectura SIMPLE de archivos en Perl
Respuesta
Básicamente, existen dos formas de lectura de archivos:
- Slurping un archivo significa leer el archivo a la vez. Esto usa mucha memoria y demora un poco, pero luego todo el contenido del archivo está en la memoria y puede hacer lo que quiera con él.
- Leer un archivo de línea por línea (en un ciclo while) es mejor si no desea leer todo el archivo (por ejemplo, detenerse cuando llegue a "banana").
Para ambas formas que necesita para crear un FILEHANDLE utilizando el comando "open", así:
open(my $yourhandle, '<', 'path/to/file.txt') # always use a variable here containing filename
or die "Unable to open file, $!";
entonces usted puede sorber el archivo poniéndolo en una matriz:
my @entire_file=<$yourhandle>; # Slurp!
o leer el archivo uno por uno usando un bucle while
while (<$yourhandle>) { # Read the file line per line (or otherwise, it's configurable).
print "The line is now in the $_ variable";
last if $_ eq 'banana'; # Leave the while-loop.
}
Después, no olvide cerrar el archivo.
close($yourhandle)
or warn "Unable to close the file handle: $!";
Eso es sólo lo básico .. hay mucho que ver con los archivos, especialmente en Tratamiento de excepciones (lo que hay que hacer cuando no existe el archivo, no es legible, se está escribiendo a), por lo que tiene que leer o pedir a distancia :)
en primer lugar, usted tiene que abrir el archivo:
open (my $SOME_FILEHANDLE, "<", "filename.txt");
Es posible que desee comprobar si la apertura del expediente se ha realizado correctamente:
open (my $SOME_FILEHANDLE, "<", "filename.txt") or die "could not open filename";
Después de abrir el archivo, puede leer la línea por línea desde $ SOME_FILEHANDLE. Se obtiene la siguiente línea con el constructo <$SOME_FILEHANDLE>
:
my $next_line = <$SOME_FILEHANDLE>;
$next_line
es indefinido tras la lectura de la última línea. Por lo tanto, se puede poner toda la cosa en un bucle while
:
while (my $next_line = <$SOME_FILEHANDLE>) {
do_something($next_line);
}
Esto funciona porque un valor indefinido evalúa a false
en la condición de tiempo.
Si desea salir del bucle cuando se encuentra "banana", es probable que utilice una expresión regular para comprobar si el plátano:
while (my $next_line = <$SOME_FILEHANDLE>) {
last if $next_line =~ /banana/;
do_something($next_line);
}
El operador last
sale del bucle while y se "dispara" cuando $next_line
coincide con banana.
René y Konerak escribieron un par de respuestas bastante buenas que muestran cómo abrir y leer un archivo. Lamentablemente, tienen algunos problemas en términos de promoción de mejores prácticas.Por lo tanto, llegaré tarde a la fiesta y trataré de agregar una explicación clara del enfoque de mejores prácticas y por qué es mejor utilizar el enfoque de mejores prácticas.
¿Qué es un archivo handle?
A identificador de archivo es un nombre que utilizamos que representa el archivo en sí. Cuando desee operar en un archivo (léalo, escríbalo, muévase, etc.) use el identificador de archivo para indicar en qué archivo operar. Un identificador de archivo es distinto del nombre o ruta del archivo.
Ámbito de la variable y el archivo se encarga de
El ámbito de una variable determina en qué partes de un programa de la variable puede ser visto. En general, es una buena idea mantener el alcance de cada variable lo más pequeño posible para que las diferentes partes de un programa complejo no se rompan entre sí.
La forma más fácil de controlar estrictamente el alcance de una variable en Perl es convertirla en una variable léxica . Las variables léxicas solo son visibles dentro del bloque en el que están declaradas. Utilice my
para declarar una variable léxica: my $foo;
# Can't see $foo here
{ my $foo = 7;
print $foo;
}
# Can't see $foo here
identificadores de archivo Perl pueden ser globales o léxico. Cuando usa abrir con una palabra simple (una cadena literal sin comillas o un sigilo), crea un identificador global. Cuando abre en un escalar léxico indefinido, crea un manipulador léxico.
open FOO, $file; # Global file handle
open my $foo, $file; # Lexical file handle
# Another way to get a lexical handle:
my $foo;
open $foo, $file;
El gran problema con los identificadores de archivos globales es que son visibles en cualquier parte del programa. Entonces, si creo un manejador de archivo llamado FOO en subrutina, debo ser muy cuidadoso para asegurarme de que no utilizo el mismo nombre en otra rutina, o si uso el mismo nombre, debo estar absolutamente seguro de que bajo ninguna circunstancia puedo ellos entran en conflicto el uno con el otro. La alternativa más simple es usar un manejador léxico que no puede tener el mismo tipo de conflictos de nombre.
Otro beneficio de los manejadores léxicos es que es fácil pasarlos como argumentos de subrutina.
La función open
La función open
tiene todo tipo de características. Puede ejecutar subprocesos, leer archivos e incluso proporcionar un control para el contenido de un escalar. Puede alimentarlo con muchos tipos diferentes de listas de argumentos. Es muy potente y flexible, pero estas características vienen con algunas trampas (la ejecución de subprocesos no es algo que quieras hacer por accidente).
Para el caso simple de abrir un archivo, lo mejor es utilizar siempre la forma 3-argumento, ya que evita la activación involuntaria de todas esas características especiales:
open FILEHANDLE, MODE, FILEPATH
FILEHANDLE
es el identificador de archivo para abrir.
MODE
es cómo abrir el archivo, >
de sobreescritura, '>>for write in append mode,
+>for read and write, and
< `para lectura.
FILEPATH
es la ruta al archivo para abrir.
En caso de éxito, open
devuelve un valor verdadero. En caso de error, $!
se configura para indicar el error y se devuelve un valor falso.
tanto, para que un identificador de archivo de léxico con un 3-argumento open
que podemos utilizar para leer un archivo:
open my $fh, '<', $file_path;
Los valores de retorno lógicas que sea fácil de comprobar si hay errores:
open my $fh, '<', $file_path
or die "Error opening $file_path - $!\n";
Me gusta reducir el tratamiento de errores a una nueva línea y aplicar sangría, pero ese es el estilo personal.
cierre maneja
Cuando usa manijas globales es crítico con cuidado, cierre explícitamente todas y cada mango cuando haya terminado con él. De lo contrario, pueden surgir errores extraños y problemas de mantenimiento.
close FOO;
léxico maneja cerrará automáticamente cuando se destruye la variable (cuando el recuento de referencias llega a 0, por lo general cuando la variable se sale del ámbito).
Cuando se utilizan manejadores léxicos, es común confiar en el cierre implícito de identificadores en lugar de cerrarlos explícitamente.
Diamantes son el mejor amigo de Perl.
El operador de diamante, <>
, nos permite iterar sobre un identificador de archivo. Al igual que open
tiene superpoderes. Ignoraremos a la mayoría de ellos por ahora. (Sin embargo, busque información en el separador de registros de entrada, el separador de registros de salida y el manejador de archivos NULL).
Lo importante es que en el contexto escalar (por ejemplo, asignar a un escalar) actúa como readline
función. En el contexto de la lista (por ejemplo, asignar a una matriz) actúa como una función read_all_lines
.
Imagínese que usted quiere leer un archivo de datos con tres líneas de cabecera (fecha, hora y ubicación) y un montón de líneas de datos:
open my $fh, '<', $file_path
or die "Ugh - $!\n";
my $date = <$fh>;
my $time = <$fh>;
my $loc = <$fh>;
my @data = <$fh>;
Está en común escuchar a la gente habla de sorber un archivo. Esto significa leer todo el archivo en una variable a la vez.
# Slurp into array
my @slurp = <$fh>;
# Slurp into a scalar - uses tricks outside the scope of this answer
my $slurp;
{ local $/ = undef; $slurp = <$fh>; }
Poniendo todo junto
open my $fh, '<', 'my_file'
or die "Error opening file - $!\n";
my @before_banana;
while(my $line = <$fh>) {
last if $line =~ /^banana$/;
push @before_banana, $line;
}
Poniendo todo junto - edición especial de crédito adicional
my $fh = get_handle('my_file');
my @banana = read_until($fh, qr/^banana$/); # Get the lines before banana
read_until($fh, qr/^no banana$/); # Skip some lines
my @potato = read_until($fh, qr/^potato$/); # Get the lines before potato
sub get_handle {
my $file_path = shift;
open my $fh, '<', $file_path
or die "Can't open '$file_path' for reading - $!\n";
return $fh;
}
sub read_until {
my $fh = shift;
my $match = shift;
my @lines;
while(my $line = <$fh>) {
last if $line =~ /$match/;
push @line, $line;
}
return @lines;
}
¿Por qué tantas maneras diferentes? ¿Por qué tantos errores?
Perl es un lenguaje antiguo; tiene un bagaje que data de 1987. A lo largo de los años se encontraron varios problemas de diseño y se hicieron arreglos, pero solo en raras ocasiones se permitieron soluciones para perjudicar la compatibilidad con versiones anteriores.
Además, Perl está diseñado para darle la flexibilidad de hacer lo que quiera, cuando lo desee. Es muy permisivo Lo bueno de esto es que puedes alcanzar las oscuras profundidades y hacer cosas mágicas realmente geniales. Lo malo es que es fácil dispararse en el pie si olvida templar su exuberancia y no centrarse en producir código legible.
El hecho de que tenga cuerda más que suficiente, no significa que deba ahorcarse.
WOW, esto es increíble. Gracias por una respuesta tan profunda, realmente lo aprecio. Esto me ayuda a entender el proceso una tonelada. – Befall
@daotoad: ¡¡¡Gran respuesta !! –
¿No se cierran los identificadores globales cuando finaliza el proceso (si no es así, efectivamente por el sistema operativo)? ¿O pueden los datos realmente perderse para un identificador de archivo global que se utiliza para escribir y no se cierra en el script de Perl? –
- 1. de archivos de lectura en la variable en Perl
- 2. procesamiento paralelo simple en perl
- 3. Lectura de la variable en Perl
- 4. Cita simple de Perl regex
- 5. Ruby: Lectura de archivos PDF
- 6. Lectura de archivos .msg
- 7. Lectura de archivos MP3
- 8. Lectura de archivos .DXF
- 9. Lectura de archivos MIDI
- 10. lectura de archivo INI simple con AS3
- 11. Análisis JSON simple usando Perl
- 12. Lectura de archivos muy grandes en PHP
- 13. simple Sistema de archivos
- 14. lectura C archivos binarios
- 15. ¿Cómo puedo configurar el tamaño del búfer de lectura de archivos en Perl para optimizarlo para archivos grandes?
- 16. FileSystemObject - Lectura de archivos Unicode
- 17. Lectura de archivos delimitados en C++
- 18. Lectura programática de archivos PDF en C#
- 19. Lectura de archivos completos en Lua
- 20. Lectura de archivos Android.mk en subdirectores recursivamente
- 21. Lectura de archivos * .wav en Python
- 22. lectura de archivos odt en php
- 23. Lectura de archivos xlsx en PHP
- 24. Lectura de archivos wav en Java
- 25. Lectura de archivos CSV en C#
- 26. Lectura de archivos .mat en Python
- 27. Lectura de archivos bmp en Python
- 28. lectura/escritura de archivos bmp en c
- 29. Archivo simple de lectura/escritura .dat en Delphi
- 30. Lectura de archivos de Excel con xlrd
¡Impresionante! Justo lo que estaba buscando, ¡gracias! – Befall
No use esto para el código de producción, esto es solo para comenzar a aprender. ¡Asegúrate de buscar excepciones en todos lados! – Konerak
Konerak, ¿podría comenzar a utilizar y enseñar los manejadores de archivos léxicos? – daxim