2010-02-22 25 views
7

Estoy buscando una manera de leer un archivo de entrada e imprimir solo líneas seleccionadas en un archivo de salida en Perl. Las líneas que quiero imprimir en el archivo de salida comienzan con xxxx.xxxx.xxxx, donde x es un carácter alfanumérico (los períodos son puntos, no comodines). Las líneas no tienen todas la misma terminación, si eso hace la diferencia. Estoy pensando en algo como lo siguiente (la condición de la declaración if es todo lo que realmente me falta).¿Cómo puedo escribir solo ciertas líneas de un archivo en Perl?

open(IN, "<$csvfile"); 
my @LINES = <IN>; 
close(IN); 
open(OUT, ">$csvnewfile"); 
print OUT @LINES if ([line starts with xxxx.xxxx.xxxx]); 
close(OUT); 

¡Gracias de antemano!

Respuesta

8

Esto es una mejor forma de bucle a través de sus líneas. Evita cargar el archivo de entrada entero en memoria a la vez:

use strict; 
use warnings; 

open my $fhi, '<', $csvfile or die "Can not open file $csvfile: $!"; 
open my $fho, '>', $csvnewfile or die "Can not open file $csvnewfile: $!"; 
while (<$fhi>) { 
    print $fho $_ if m/^ \w{4} \. \w{4} \. \w{4} /x; 
} 
close $fho; 
close $fhi; 

Tenga en cuenta que la clase \w personaje también incluye guiones bajos. Para evitar subrayado:

print $fho $_ if m/^ [a-z\d]{4} \. [a-z\d]{4} \. [a-z\d]{4} /xi; 
+2

Es posible que desee agregar un modificador '/ i' a esa segunda expresión regular también ... –

+1

¡Gracias! Lo único que faltaba era '$ _' después de' $ fho' en la sentencia 'if' (tardé un poco en encontrar eso, en realidad ...) – ryantmer

+1

@ryantmer: Sí, mi código no se había probado. Actualicé mi publicación. Fui perezoso para crear cualquier entrada falsa para probar mi código, por lo que es una gran idea proporcionar una pequeña muestra de entrada con su pregunta. – toolic

1
if ($_ =~ m/^\w{4}\.\w{4}\.\w{4}/i) 

Yo creo . Mi perl está un poco oxidado.

0

Si no le importa dejándola como una línea de comandos de línea 1:

perl -ne "print if /^.{4}[.].{4}[.].{4}/" csvfile.csv > csvnewfile.csv 
3

consejos de estilo:

  • uso filehandles léxicas
  • comprobar el resultado de open
  • también una buena idea para comprobar el resultado de close en un mango abierto para escritura

Ver a continuación:

#! /usr/bin/perl 

use warnings; 
use strict; 

die "Usage: $0 old new\n" unless @ARGV == 2; 

my($csvfile,$csvnewfile) = @ARGV; 

open my $in, "<", $csvfile or die "$0: open $csvfile: $!"; 
open my $out, ">", $csvnewfile or die "$0: open $csvnewfile: $!"; 

while (<$in>) { 
    print $out $_ if /^\w{4}\.\w{4}\.\w{4}/; 
} 

close $out or warn "$0: close $csvnewfile: $!"; 
2

usando grep

grep "^\w\{4\}\.\w\{4\}\.\w\{4\}\b" file 
+1

Eso está en la línea de comandos, no en perl BTW. Es para lo que es 'grep'. Si no tiene un 'grep' moderno, puede necesitar' egrep' o una expresión regular más antigua como '^ [0-9a-zA-Z.] {14}' o lo que sea. – Nathan

+0

sí, en la línea de comando. Supongo que la etiqueta 'grep' es la * nix grep, no la de Perl. – ghostdog74

0
perl -ne 'print if /^\w{4}\.\w{4}\.\w{4}\b/' file > newfile.csv 
1

De respuesta perlfaq5 's de How do I change, delete, or insert a line in a file, or append to the beginning of a file?


La idea básica de inserción, cambio o supresión de una línea de un archivo de texto implica la lectura e imprima el archivo hasta el punto donde desea realizar el cambio, realizando el cambio, luego leyendo e imprimiendo el resto del archivo. le. Perl no proporciona acceso aleatorio a las líneas (especialmente porque el separador de entrada de registro, $ /, es mutable), aunque módulos como Tie :: File pueden simularlo.

programa

Un Perl para hacer estas tareas toma la forma básica de la apertura de un archivo, imprimir sus líneas, a continuación, cierre el archivo:

open my $in, '<', $file  or die "Can't read old file: $!"; 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

while(<$in>) 
    { 
    print $out $_; 
    } 

cerca de $ cabo; Dentro de esa forma básica, agregue las partes que necesita para insertar, cambiar o eliminar líneas.

Para anteponer las líneas al principio, imprima esas líneas antes de ingresar al ciclo que imprime las líneas existentes.

open my $in, '<', $file  or die "Can't read old file: $!"; 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

print $out "# Add this line to the top\n"; # <--- HERE'S THE MAGIC 

while(<$in>) 
    { 
    print $out $_; 
    } 

cerrar $ out; Para cambiar las líneas existentes, inserte el código para modificar las líneas dentro del ciclo while. En este caso, el código encuentra todas las versiones en minúscula de "perl" y las mayúsculas. ¡Sucede en cada línea, así que asegúrese de hacer eso en todas las líneas!

open my $in, '<', $file  or die "Can't read old file: $!"; 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

print $out "# Add this line to the top\n"; 

while(<$in>) 
    { 
    s/\b(perl)\b/Perl/g; 
    print $out $_; 
    } 

cerrar $ out; Para cambiar solo una línea en particular, el número de línea de entrada, $., Es útil. Primero lea e imprima las líneas hasta la que desea cambiar. A continuación, lea la única línea que desea cambiar, cámbiela e imprímala. Después de eso, lea el resto de las líneas e imprimir los:

while(<$in>) # print the lines before the change 
    { 
    print $out $_; 
    last if $. == 4; # line number before change 
    } 

my $line = <$in>; 
$line =~ s/\b(perl)\b/Perl/g; 
print $out $line; 

while(<$in>) # print the rest of the lines 
    { 
    print $out $_; 
    } 

Para saltar líneas, utilice los controles de bucle. El siguiente en este ejemplo omite las líneas de comentario, y el último detiene todo el procesamiento una vez que encuentra END o DATA.

while(<$in>) 
    { 
    next if /^\s+#/;    # skip comment lines 
    last if /^__(END|DATA)__$/; # stop at end of code marker 
    print $out $_; 
    } 

hacer el mismo tipo de cosas para eliminar una línea en particular mediante el uso junto a saltar las líneas que no desea que aparezca en la salida. Este ejemplo se salta cada cinco líneas:

while(<$in>) 
    { 
    next unless $. % 5; 
    print $out $_; 
    } 

Si, por alguna extraña razón, que realmente quiere ver todo el archivo a la vez en lugar de procesar la línea por línea, puede sorber en (siempre y cuando se puede adaptarse a toda la cosa en la memoria):

open my $in, '<', $file  or die "Can't read old file: $!" 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

my @lines = do { local $/; <$in> }; # slurp! 

    # do your magic here 

print $out @lines; 

módulos tales como File :: Slurp y corbata :: archivos puede ayudar con eso también. Si puede, sin embargo, evite leer todo el archivo a la vez. Perl no devolverá esa memoria al sistema operativo hasta que el proceso finalice.

También puede usar uniones Perl para modificar un archivo en el lugar. Lo siguiente cambia todo 'Fred' a 'Barney' en inFile.txt, sobrescribiendo el archivo con los nuevos contenidos. Con el modificador -p, Perl enrolla un ciclo while alrededor del código que especifique con -e, y -i activa la edición in situ. La línea actual está en $ . Con -p, Perl imprime automáticamente el valor de $ al final del ciclo. Ver perlrun para más detalles.

perl -pi -e 's/Fred/Barney/' inFile.txt 

Para realizar una copia de seguridad de inFile.txt, dar extensión de archivo -ia añadir:

perl -pi.bak -e 's/Fred/Barney/' inFile.txt 

Para cambiar sólo la quinta línea, se puede añadir un $ que controla la prueba, la línea de entrada. número, entonces sólo realizar la operación cuando pasa la prueba:

perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt 

Para agregar líneas antes de una determinada línea, se puede añadir una línea antes de Perl imprime _ $ (o líneas!):

perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt 

Usted puede incluso agregar una línea al comienzo de un archivo, ya que las impresiones de la línea de corriente al final del bucle:

perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt 

Para insertar una línea después de que uno ya está en el archivo, el uso el -n cambiar. Es como -p excepto que no imprime $ _ al final del ciclo, por lo que debe hacerlo usted mismo.En este caso, imprima $ _ primero, luego imprima la línea que desea agregar.

perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt 

Para eliminar líneas, solo imprima las que desee.

perl -ni -e 'print unless /d/' inFile.txt 

    ... or ... 

perl -pi -e 'next unless /d/' inFile.txt 
Cuestiones relacionadas