2010-04-11 7 views
22

non posso entrare in modifica sul posto Perl one-liners che girano sotto ActivePerl a lavorare a meno che non li specificare con un'estensione di backup:Perché è necessario specificare l'opzione -i con un'estensione di backup quando si utilizza ActivePerl?

C:\> perl -i -ape "splice (@F, 2, 0, q(inserted text)); $_ = qq(@F\n);" file1.txt 
Can't do inplace edit without backup. 

Lo stesso comando con -i.bak o -i.orig funziona a meraviglia, ma crea un file di backup indesiderati nel processo.

C'è un modo per aggirare questo?

risposta

29

Questa è una limitazione di Windows/MS-DOS. Secondo perldiag:

Sei su un sistema come MS-DOS che si confonde se si prova leggendo da un file eliminato (ma ancora aperto). Devi dire -i.bak, o alcuni di questi.

-i implementazione di Perl induce a eliminare file1.txt mantenendo un handle aperto ad esso, quindi ricreare il file con lo stesso nome. Ciò consente di "leggere" file1.txt anche se è stato cancellato e viene ricreato. Sfortunatamente, Windows/MS-DOS non ti permette di cancellare un file che ha un handle aperto collegato ad esso, quindi questo meccanismo non funziona.

La soluzione migliore è utilizzare -i.bak e quindi eliminare il file di backup. Questo almeno ti dà una certa protezione - per esempio, puoi scegliere di non cancellare il backup se perl esce con un codice di uscita diverso da zero. Qualcosa del tipo:

perl -i.bak -ape "splice...." file1.txt && del file1.bak 
+0

Quindi è un limite di Windows. Speravo che non avrei dovuto 'disconnettere' il backup con un comando separato ... sembra che dovrò. Grazie per l'aiuto. – Zaid

+0

Non interamente correlato, ma la modifica sul posto su sed in windows sembra funzionare per me. Posso vedere che il tuo esempio non funzionerebbe in sed, ma potrebbe essere utile sapere. – Mike

+0

@Mike: Da parte mia, la modifica sul posto di 'sed' lascia file temporanei come ad es. 'sedGihEwg' nel file system - il tuo no? Quale versione hai? Sto usando la versione 4.2.1 di GNU sed. – zb226

0

Esempio con modifica ricorsiva ed eliminazione entrambe eseguite da trova. Funziona ad es. Mi sono imbattuto in Windows.

$ find . -name "*.xml" -print0 | xargs -0 perl -p -i.bak -e 's#\s*<property name="blah" value="false" />\s*##g' 
$ find . -name "*.bak" -print0 | xargs -0 rm 

Valori terminati binari passati tra find/xargs per gestire gli spazi. Insolito s/prefisso per evitare mangling xml nel termine di ricerca. Ciò presuppone che non ci fossero file .bak in sospeso per iniziare.