2009-05-27 15 views
6

Ho il seguente script che accetta un file di input, il file di output e sostituisce la stringa nel file di input con un'altra stringa e scrive il file di output.Come posso eseguire ricerche in blocco e sostituire con Perl?

voglio cambiare lo script per attraversare attraverso una directory di file cioè anziché chiedere file di input e di output, lo script dovrebbe prendere come argomento un percorso di directory ad esempio C: \ temp \ allFilesTobeReplaced \ e di ricerca per una stringa x e sostituirla con y per tutti i file sotto il percorso di directory e scrivere gli stessi file.

Come posso fare?

Grazie.

$file=$ARGV[0]; 

open(INFO,$file); 
@lines=<INFO>; 
print @lines; 

open(INFO,">c:/filelist.txt"); 

foreach $file (@lines){ 
    #print "$file\n"; 
    print INFO "$file"; 
} 

#print "Input file name: "; 
#chomp($infilename = <STDIN>); 

if ($ARGV[0]){ 
    $file= $ARGV[0] 
} 

print "Output file name: "; 
chomp($outfilename = <STDIN>); 
print "Search string: "; 
chomp($search = <STDIN>); 
print "Replacement string: "; 
chomp($replace = <STDIN>); 

open(INFO,$file); 
@lines=<INFO>; 
open(OUT,">$outfilename") || die "cannot create $outfilename: $!"; 

foreach $file (@lines){  
    # read a line from file IN into $_ 
    s/$search/$replace/g; # change the lines 
    print OUT $_; # print that line to file OUT 
} 
close(IN); 
close(OUT); 

risposta

11

L'uso della perl singolo rivestimento

perl -pi -e 's/original string/new string/' filename 

può essere combinato con File::Find, per dare il seguente script singola (questo è un modello che uso per molte di queste operazioni).

use File::Find; 

# search for files down a directory hierarchy ('.' taken for this example) 
find(\&wanted, "."); 

sub wanted 
{ 
    if (-f $_) 
    { 
     # for the files we are interested in call edit_file(). 
     edit_file($_); 
    } 
} 

sub edit_file 
{ 
    my ($filename) = @_; 

    # you can re-create the one-liner above by localizing @ARGV as the list of 
    # files the <> will process, and localizing $^I as the name of the backup file. 
    local (@ARGV) = ($filename); 
    local($^I) = '.bak'; 

    while (<>) 
    { 
     s/original string/new string/g; 
    } 
    continue 
    { 
     print; 
    } 
} 
1

So che è possibile utilizzare un semplice Per l one-liner dalla riga di comando, dove nomefile può essere un singolo nome file o un elenco di nomi di file. Probabilmente si potrebbe combinare questo con la risposta di BGY per ottenere l'effetto desiderato:

perl -pi -e 's/original string/new string/' filename 

E io so che è banale, ma questo suona un po 'come sed, se è possibile utilizzare gli strumenti GNU:

for i in `find ./allFilesTobeReplaced`; do sed -i s/original string/new string/g $i; done 
2

Si può fare questo con il parametro -i:

Basta elaborare tutti i file come normale, ma includono -i.bak:

#!/usr/bin/perl -i.bak 

while (<>) { 
    s/before/after/; 
    print; 
} 

Questo dovrebbe elaborare ogni file, e rinominare l'originale in original.bak E naturalmente puoi farlo come one-liner come menzionato da @Jamie Cook

-1

perl -pi -e # # # # NUOVO # g 'nome file. È possibile sostituire il nome file con il modello che si adatta al proprio elenco di file.

Problemi correlati