Ho un file di testo da 25 GB che necessita di una stringa sostituita su poche righe. Posso usarlo sed
con successo ma ci vuole molto tempo per eseguirlo.
sed -i 's|old text|new text|g' gigantic_file.sql
C'è un modo più rapido per farlo?
Ho un file di testo da 25 GB che necessita di una stringa sostituita su poche righe. Posso usarlo sed
con successo ma ci vuole molto tempo per eseguirlo.
sed -i 's|old text|new text|g' gigantic_file.sql
C'è un modo più rapido per farlo?
Risposte:
Puoi provare:
sed -i '/old text/ s//new text/g' gigantic_file.sql
Da questo ref :
OTTIMIZZAZIONE PER LA VELOCITÀ: se è necessario aumentare la velocità di esecuzione (a causa di file di input di grandi dimensioni o processori lenti o dischi rigidi), la sostituzione verrà eseguita più rapidamente se viene specificata l'espressione "trova" prima di dare "s /.../. ../ "istruzione.
Ecco un confronto su un file 10G. Prima:
$ time sed -i 's/original/ketan/g' wiki10gb
real 5m14.823s
user 1m42.732s
sys 1m51.123s
Dopo:
$ time sed -i '/ketan/ s//original/g' wiki10gb
real 4m33.141s
user 1m20.940s
sys 1m44.451s
sed
è errato. Ho modificato questo post ieri per correggere l'ultimo sed
comando che dovrebbe essere time sed -i '/original/ s//ketan/g' wiki10gb
e non time sed -i '/ketan/ s//original/g' wiki10gb
. Oggi sto ripristinando la mia modifica perché 1. i tempi non corrispondono più al comando e 2. Ho fatto lo stesso test con GNU sed su un file da 3+ GB e non osservo alcuna differenza tra le due sed
alternative. Sospetto che la differenza nei tempi sia dovuta all'errore di ortografia.
time
risultati personalmente, ma tutto sommato, non c'è stata alcuna differenza nel tempo.
La risposta breve è "No" - il fattore che limita questo tipo di operazione è l'IO del disco. Non è possibile eseguire lo streaming di 25 GB di un disco più velocemente. Potresti ottenere un miglioramento minore se non esegui la modifica in loco e scrivi il risultato di sed
su un'unità separata (se ne hai una disponibile), perché in questo modo puoi leggere da una, mentre scrivi su un'altra e c'è leggermente di conseguenza meno contesa.
Si potrebbe essere in grado di accelerarlo un po 'non usando il motore di espressioni regolari per ogni linea - così per esempio usando perl (io sono abbastanza sicuro che si può fare questo con sed
, ma non so la sintassi) - questo partirà da linea 10.000 in poi.
perl -pe '$. > 10_000 && s/old_text/new_text/g'
E se c'è qualche tipo di complicanza nel RE (metacaratteri), minimizzare quelli migliorerà leggermente l'efficienza del motore regex.
sed -i '10000,$ s/old_text/new_text/g'
sed
confronta - presumo leggermente più veloce, ma non molto a causa delle dimensioni del file.
sed
in perl
, ma quest'ultimo permette anche di scrivere più prolisso script troppo.
Se i nuovi e vecchi testi hanno la stessa lunghezza, puoi cercare nel file e scrivere solo i byte modificati, invece di copiare l'intero file. Altrimenti rimani intrappolato nello spostamento di molti dati.
Nota: questo è complicato e comporta la scrittura di codice personalizzato.
Vedi la pagina man di fseek se stai lavorando in C o C ++, o i tuoi wrapper di lingua preferiti per le chiamate di sistema di ricerca e scrittura.
Se insisti nell'usare solo la riga di comando e puoi ottenere gli offset di byte del testo, puoi scrivere il testo sostitutivo con comandi "dd" accuratamente scritti.