2009-04-17 11 views
20

Adición de un Perl estándar de archivo de función abierto a cada secuencia de comandos que tengo es un poco molesto:manera más fácil de abrir un archivo de texto y leerlo en una matriz con Perl

sub openfile{ 
    (my $filename) = @_; 
    open FILE,"$filename" or die $!; 
    my @lines = <FILE>; 
    return @lines; 
} 

y puedo crear un módulo de Perl para haz esto, pero esto es tan simple que estoy seguro de que ya debería haber uno.

Estoy tratando de encontrar una manera de leer un archivo de texto en una matriz, y no puedo encontrar un módulo Perl que pueda hacer esta simple tarea ... tal vez estoy buscando demasiado y ya vino con la instalación estándar 5.10.

De manera óptima creo que sería algo como esto:

my @lines = Module::File::Read("c:\some\folder\structure\file.txt"); 
+0

Yo recomendaría texto CSV :: :: Slurp para cualquiera que desee trabajar con archivos CSV . Este módulo funcionó mucho mejor que los otros dos o tres que probé. El siguiente mejor fue CSV :: Slurp :: Simple o algo parecido, aunque no tan robusto como Text :: CSV :: Slurp. – Brian

+2

Usar la forma 3 arg de 'open()' http://p3rl.org/open –

Respuesta

27

Usted tiene varias opciones, el clásico método de hacer:

my @array = do { 
    open my $fh, "<", $filename 
     or die "could not open $filename: $!"; 
    <$fh>; 
}; 

El método IO::All:

use IO::All; 

my @array = io($filename)->slurp; 

El método File::Slurp:

use File::Slurp; 

my @array = read_file($filename); 

Y probablemente muchos más, después de todo TIMTOWTDI.

+0

Definitivamente como el método File :: Slurp. Muchas gracias! – Brian

+0

Tenga en cuenta que File :: Slurp es anterior a las capas Perl IO y, por lo tanto, no respetará la configuración 'PERL_UNICODE' /' perl -C' que puede ser sorprendente cuando intenta escribir scripts Perl con la compatibilidad adecuada con Unicode. Path :: Tiny podría ser una alternativa con mejor soporte Unicode. –

15

que es el famoso "modo slurp":

my @lines = <FILEHANDLE> ; 

también puede ver Perl Slurp Ease

+1

"modo sorber" se usa más comúnmente para significar leer todo el archivo en un único escalar, configurando el separador de registro $/a undef. – ysth

+0

He visto el contexto escalar y de matriz descrito como modo de sorbido, pero he visto el estilo de matriz usado con más frecuencia. – codehearted

4

Has obtenido las técnicas generales, pero quiero poner en ese tipo de Perl que te desanima de hacer eso porque es muy a menudo el caso de que puedes hacer lo mismo que estás haciendo una línea -a la vez, que es intrínsecamente mucho más eficiente.

+0

Un buen punto, especialmente al leer en una matriz. Las matrices implican un procesamiento secuencial por líneas (o registros si se usa $ /), que a menudo se realiza mejor con un solo elemento a la vez. Sin embargo, hay casos en los que es apropiado sorber. –

6

Es posible que también desee considerar el uso de Tie :: File, especialmente si está leyendo archivos más grandes y no desea leer todo el archivo en la memoria. Es un módulo central. Además, consulte perlfaq5.

2

Para rápido y sucio, me gusta más la simplicidad de la limpieza con @ARGV.

# Ysth is right, it doesn't automatically die; I need another line. 
use 5.010; 
use strict; 
my @rows = do { 
    use warnings FATAL => 'inplace'; # oddly enough, this is the one. ?? 
    @ARGV='/a/file/somewhere'; 
    <>; 
}; 
say q(Not gettin' here.); 

Si Perl * no puede abrir el archivo, se muere de forma automática.


* - el ejecutable, así que no lo utilice en mayúsculas.

+1

¡No sabía que Perl no era una abreviación! Gracias por el aviso. – Brian

+1

Disculpe, la nota no era para usted sino para la notoria banda Capital-P. Irrumpirán en su publicación y capitalizarán sus P cuando específicamente se refirió al ejecutable. El idioma obtiene una P mayúscula solo. Sin embargo, no hay un anagrama. – Axeman

+0

re.pl # su perl, pero es un read-eval-parse-loop :) –

6

También eche un vistazo a Perl6::Slurp que implementa la versión Perl6 de slurp y se recomienda en el libro "Perl Best Practices".

Algunos ejemplos ....

my @lines   = slurp 'filename'; 
my @lines_chomped = slurp 'filename', { chomp => 1 }; 
my @lines_utf8 = slurp 'filename', { utf8 => 1 }; 
1

Yo recomendaría un enfoque orientado a objeto que no requiere módulos fuera de la distribución CORE y funcionará en cualquier lugar:

use strict; 
use warnings; 
use IO::File; 
my $fh = IO::File->new("< $file"); 

foreach ($fh->getlines) { 
    do_something($_); 
} 
$fh->close 
Cuestiones relacionadas