2009-06-23 20 views
44

Sé que este tipo de preguntas ya se han hecho muchas veces antes. La razón por la que vuelvo aquí es porque siento que me he perdido algo simple y fundamental.Búsqueda de múltiples líneas reemplazar con Perl

¿Es posible mejorar este tipo de rutina de búsqueda y reemplazo? Por ejemplo, sin abrir el mismo archivo dos veces. También consejos relacionados con la velocidad son bienvenidos.

Tenga en cuenta que esto funciona con coincidencias de líneas múltiples y reemplaza también cadenas de líneas múltiples.

#!/bin/perl -w -0777 

local $/ = undef; 

open INFILE, $full_file_path or die "Could not open file. $!"; 
$string = <INFILE>; 
close INFILE; 

$string =~ s/START.*STOP/$replace_string/sm; 

open OUTFILE, ">", $full_file_path or die "Could not open file. $!"; 
print OUTFILE ($string); 
close OUTFILE; 
+0

Parece que está intentando editar el archivo en su lugar. Es decir, ábralo tanto para leer como para escribir. ¿Es eso correcto? –

+0

Sí, editando el archivo en su lugar. Ese es el caso de uso más común para mí. – user44556

Respuesta

80

Este tipo de búsqueda y reemplazo se puede lograr con una sola línea, tales como -

perl -i -pe 's/START.*STOP/replace_string/g' file_to_change 

Para más formas de lograr lo mismo echa un vistazo a este thread. Para manejar varias líneas búsquedas use el siguiente comando -

perl -i -pe 'BEGIN{undef $/;} s/START.*STOP/replace_string/smg' file_to_change 

Con el fin de convertir el código siguiente en una sola línea de un programa Perl echar un vistazo a la perlrun documentation.

Si realmente encuentra la necesidad de convertir esto en un programa de trabajo, simplemente deje que Perl maneje el archivo de apertura/cierre por usted.

#!/usr/bin/perl -pi 
#multi-line in place substitute - subs.pl 
use strict; 
use warnings; 

BEGIN {undef $/;} 

s/START.*STOP/replace_string/smg; 

Entonces puede llamar al script con el nombre de archivo como el primer argumento

$perl subs.pl file_to_change 

Si desea un guión más sustancioso donde se llega a manejar el archivo abierto/operaciones de cierre (¿no es cierto amo todas esas declaraciones de 'morir') luego eche un vistazo al ejemplo en perlrun bajo el modificador -i [extensión].

+0

¿Cómo se convierte este delineador a código de perl real? ¿Se pone feo? – user44556

+1

Y esto no parece funcionar con la coincidencia de líneas múltiples – user44556

+0

Eso es correcto, porque esto funciona en cada línea por sí mismo. –

2

Teniendo en cuenta que sorber en todo el contenido del archivo con:

local $/ = undef; 

open INFILE, $full_file_path or die "Could not open file. $!"; 
$string = <INFILE>; 
close INFILE; 

y luego hacer todo el procesamiento con $string, no hay conexión entre la forma de manejar el archivo y cómo se procesa el contenido. Tendría un problema si abrió el archivo para escribir antes de terminar de leerlo, ya que al abrir un archivo para escritura crea un nuevo archivo, descartando los contenidos anteriores.

Si todo lo que estás tratando de hacer es guardar en las declaraciones de abrir/cerrar, hazlo como Jonathan Leffer suggested. Si su pregunta es acerca de la búsqueda y el reemplazo de líneas múltiples, entonces aclare cuál es el problema.

+0

Se trata de búsqueda y reemplazo de líneas múltiples genéricas. ¿Está realmente bien que abra el mismo puntero de archivo otra vez, incluso si el archivo es muy grande? En líneas simples parece que no hay necesidad de abrir el mismo archivo dos veces. Todavía me falta algo aquí. Quizás debería ver el ejemplo de Jonathan en práctica. – user44556

+0

crear un manejador de archivos no tiene nada que ver con el tamaño del archivo. Es solo un puntero. El acto de abrir un archivo no implica leer su contenido. –

+0

Creo que esto está cerca de mi malentendido. ¿Cómo abrir el mismo archivo una vez tanto para leer como para escribir cuando se lee significa la operación necesaria de llevarlo a cabo para encontrar posibles coincidencias? – user44556

1

Trayendo la respuesta breve de los comentarios, para cualquiera que busque una línea rápida, y la razón por la cual Perl ignora sus opciones de RegEx desde la línea de comando.

perl -0pe 's/search/replace/gms' file

Sin el argumento -0, Perl procesa los datos line-by-line, lo que hace que las búsquedas de varias líneas fallen.

Cuestiones relacionadas