¿Cómo cambio, elimino o inserto una línea en un archivo o añado al comienzo de un archivo en Perl?

La gente sigue haciendo esta pregunta y sigo respondiéndola con la misma respuesta de perlfaq5 . Ahora es algo a lo que podemos apuntar en Stackoverflow.

Desde perlfaq5 :

La idea básica de insertar, cambiar o eliminar una línea de un archivo de texto implica leer e imprimir el archivo hasta el punto que desea realizar el cambio, hacer el cambio, luego leer e imprimir el rest del archivo. 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.

Un progtwig de Perl para realizar estas tareas toma la forma básica de abrir un archivo, imprimir sus líneas y luego cerrar 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 $_; } close $out; 

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 $_; } close $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 para 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 $_; } close $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 rest de las líneas e imprímalas:

 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 saltear líneas, use los controles de bucle. El next en este ejemplo omite las líneas de comentario, y el last 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 $_; } 

Haga lo mismo para eliminar una línea en particular usando next para omitir las líneas que no desea mostrar en la salida. Este ejemplo omite cada quinta línea:

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

Si, por algún motivo extraño, realmente desea ver el archivo completo a la vez en lugar de procesar línea por línea, puede sorberlo (¡siempre que pueda guardar todo 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; 

Los módulos como File :: Slurp y Tie :: File también pueden ayudar con eso. 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 Perl one-liners para modificar un archivo in situ. Lo siguiente cambia todo ‘Fred’ a ‘Barney’ en inFile.txt , sobrescribiendo el archivo con los nuevos contenidos. Con el -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 hacer una copia de seguridad de inFile.txt , brinde -i una extensión de archivo para agregar:

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

Para cambiar solo la quinta línea, puede agregar una comprobación de comprobación $. , el número de línea de entrada, luego solo realice la operación cuando pase la prueba:

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

Para agregar líneas antes de cierta línea, puede agregar una línea (¡o líneas!) Antes de que Perl imprima $_ :

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

Incluso puede agregar una línea al comienzo de un archivo, ya que la línea actual se imprime al final del ciclo:

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

Para insertar una línea después de una que ya está en el archivo, use el -n . 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