2015-04-01 4 views
7

UtilizzandoCome sostituire una stringa in un file esistente in Perl, mentre non tocca i file non modificati

perl -pi -e 's/pattern/replacement/g' $(find src -type f) 

è bello, tranne che per una cosa: tutti i file vengono sovrascritti, anche quelli senza alcuna partita. Questo non va bene dato che spesso mantengo molti di loro aperti in Emacs o Eclipse che poi mi fanno domande noiose. C'è un modo semplice per evitare di toccare file non modificati (Qualcosa come l'uso di grep in find è troppo lavoro, specialmente per motivi complessi).

risposta

4

La primissima cosa -i dopo l'apertura di un file è unlink, quindi ciò significa che non è possibile utilizzare -i sui file che non si desidera modificare.

find src -type f -exec grep -Pl 'pattern' {} + | 
    xargs perl -i -pe's/pattern/replacement/g' 

Naturalmente, grep possono già eseguire ricerche ricorsive, quindi a meno che non è necessario utilizzare find per filtrare oltre hai indicato i risultati, è possibile utilizzare

grep -Plr 'pattern' src | 
    xargs perl -i -pe's/pattern/replacement/g' 

Nota: cmd | xargs perl ... can gestire più file di perl ... $(cmd).

+0

Puoi spiegare la tua nota su 'xargs'? – maaartinus

+0

@maaartinus, C'è un limite alla dimensione delle righe di comando. È molto più grande di un tempo, ma non è così difficile da raggiungere. 'xargs' risolve questo problema avviando il programma più di una volta se necessario. Ad esempio, eseguirà 'foo file1 file2 ... file499' e' foo file500 file501 ... file999' invece eseguendo 'foo file1 file2 ... file999' se quest'ultimo non è possibile. – ikegami

2

-p

provoca Perl ad assumere il seguente ciclo intorno al vostro programma, che lo rende un'iterazione su argomenti nomi di file un po 'come sed:

LINE: 
while (<>) { 
    ... # your program goes here 
} continue { 
    print or die "-p destination: $!\n"; 
} 

-i [estensione]

è equivalente a

#!/usr/bin/perl 
$extension = '.orig'; 
LINE: while (<>) { 
    if ($ARGV ne $oldargv) { 
     if ($extension !~ /\*/) { 
      $backup = $ARGV . $extension; 
     } 
     else { 
      ($backup = $extension) =~ s/\*/$ARGV/g; 
     } 
     rename($ARGV, $backup); 
     open(ARGVOUT, ">$ARGV"); 
     select(ARGVOUT); 
     $oldargv = $ARGV; 
    } 
    s/foo/bar/; 
} 
continue { 
    print; # this prints to original filename 
} 
select(STDOUT); 

Ora, ciò significa che è possibile prendere questo script di scheletro e modificare ripristinare il backup se non sono state apportate sostituzioni.

4

Invece di passare tutti i file a perl per essere elaborati, preselezionarli da soli.

Trovare i file che hanno pattern in loro:

grep -Plr 'pattern' src 

quindi utilizzare tale, invece di che find chiamata:

perl -pi -e 's/pattern/replacement/g' $(grep -Plr pattern src) 

e neppure come questo:

grep -Plr 'pattern' src | xargs perl -pi -e's/pattern/replacement/g' 

Questa volontà probabilmente anche più veloce perché non stai elaborando i file inutilmente.

Problemi correlati