2009-06-23 14 views
44

So che questo tipo di domande sono già state fatte molte volte. Il motivo per cui vengo di nuovo qui è che mi sembra di aver perso qualcosa di semplice e fondamentale.Sostituire la ricerca multilinea con Perl

È possibile rendere questo tipo di routine di sostituzione della ricerca migliore. Ad esempio senza aprire lo stesso file due volte. Anche i consigli relativi alla velocità sono ben accetti.

Si noti che questo funziona con corrispondenze multilinea e sostituisce anche stringhe multilinea.

#!/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

Sembra che tu stia cercando di modificare il file sul posto. Cioè, aprilo per leggere e per scrivere. È corretto? –

+0

Sì, modifica del file in posizione. Questo è il caso d'uso più comune per me. – user44556

risposta

80

Questo tipo di ricerca e sostituzione può essere realizzato con una battuta, come -

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

Per altri modi per ottenere la stessa cosa controllare questo thread. Per gestire più linee ricerche utilizzare il seguente comando -

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

Al fine di convertire il codice da un one-liner ad un programma Perl hanno uno sguardo al perlrun documentation.

Se si trova davvero la necessità di convertirlo in un programma funzionante, basta lasciare che Perl gestisca l'apertura/chiusura del file per conto dell'utente.

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

BEGIN {undef $/;} 

s/START.*STOP/replace_string/smg; 

È quindi possibile chiamare lo script con il nome del file come primo argomento

$perl subs.pl file_to_change 

Se si desidera uno script più carnoso dove si arriva a gestire il file aperto/chiudi le operazioni (non è vero amo tutte quelle dichiarazioni 'die') quindi dai un'occhiata all'esempio in perlrun sotto l'opzione -i [estensione].

+0

Come si converte questo liner in codice perl effettivo? Diventa brutto? – user44556

+1

E questo non sembra funzionare con la corrispondenza multilinea – user44556

+0

Esatto, perché funziona su ogni singola riga. –

2

Considerando che si slurp in tutto il contenuto del file con:

local $/ = undef; 

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

e poi fare tutte le lavorazioni con $string, non c'è alcuna connessione tra il modo di gestire il file e come si elaborano i contenuti. Avresti un problema se avessi aperto il file per la scrittura prima che avessi finito di leggerlo, poiché aprire un file per scrivere crea un nuovo file, scartando i contenuti precedenti.

Se tutto ciò che si sta tentando di fare è salvare su dichiarazioni di apertura/chiusura, quindi fare come Jonathan Leffer suggested. Se la tua domanda riguarda la ricerca e la sostituzione multilinea, ti preghiamo di chiarire qual è il problema.

+0

Riguarda la ricerca e la sostituzione multilinea generica. Va davvero bene che apro di nuovo lo stesso puntatore del file anche se il file è molto grande? In one-liner sembra non esserci la necessità di aprire lo stesso file due volte. Mi manca ancora qualcosa qui. Forse dovrei vedere l'esempio di Jonathan in pratica. – user44556

+0

creazione di un gestore di file non ha nulla a che fare con le dimensioni del file. È solo un puntatore. L'atto di aprire un file non implica la lettura del suo contenuto. –

+0

Penso che questo sia da qualche parte vicino al mio fraintendimento. Come aprire lo stesso file una volta sia per la lettura che per la scrittura durante la lettura significa l'operazione necessaria per la ricerca di corrispondenze possibili? – user44556

1

Estrarre la risposta breve dai commenti, per chiunque sia alla ricerca di un quick one-liner e il motivo per cui Perl sta ignorando le loro opzioni RegEx dalla riga di comando.

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

senza l'argomento -0, Perl elabora i dati line-by-line, che fa sì che le ricerche multilinea al sicuro.

Problemi correlati