I miei test hanno indicato che sed
può diventare legato alla CPU abbastanza facilmente su qualcosa di simile. Se hai una macchina multi-core puoi provare a generare più sed
process con uno script simile a questo:
#!/bin/sh
INFILE=data.txt
OUTFILE=fixed.txt
SEDSCRIPT=script.sed
SPLITLIMIT=`wc -l $INFILE | awk '{print $1 / 20}'`
split -d -l $SPLITLIMT $INFILE x_
for chunk in ls x_??
do
sed -f $SEDSCRIPT $chunk > $chunk.out &
done
wait
cat x_??.out >> output.txt
rm -f x_??
rm -f x_??.out
Prova a cambiare le prime due righe in:
s/[ \t]*|[ \t]*/|/g
Il meglio che sono riuscito a fare con sed è stato questo script:
s/[\s\t]*|[\s\t]*/|/g
s/[\s\t]*$//
s/^|/null|/
Nei miei test, questo è stato eseguito circa il 30% più velocemente del tuo script sed. L'aumento delle prestazioni deriva dalla combinazione delle prime due espressioni regolari e dall'omissione del flag "g" dove non è necessario.
Tuttavia, il 30% più veloce è solo un lieve miglioramento (dovrebbe comunque essere necessaria circa un'ora e mezza per eseguire lo script di cui sopra sul file di dati da 1 GB). Volevo vedere se potevo fare di meglio.
Alla fine, nessun altro metodo che ho provato (awk, perl e altri approcci con sed) è andato meglio, tranne - ovviamente - una semplice implementazione C. Come ci si aspetterebbe con C, il codice è un po' prolisso per essere postato qui, ma se vuoi un programma che sia probabilmente più veloce di qualsiasi altro metodo là fuori, potresti voler dare un'occhiata.
Nei miei test, l'implementazione C termina in circa il 20% del tempo necessario per lo script sed. Quindi potrebbero essere necessari circa 25 minuti per l'esecuzione sul tuo server Unix.
Non ho passato molto tempo a ottimizzare l'implementazione C. Senza dubbio ci sono un certo numero di punti in cui l'algoritmo potrebbe essere migliorato, ma francamente, non so se sia possibile risparmiare una quantità significativa di tempo oltre a ciò che già raggiunge. Semmai, penso che certamente ponga un limite massimo al tipo di prestazioni che puoi aspettarti da altri metodi (sed, awk, perl, python, ecc.).
Modifica: La versione originale aveva un bug minore che causava la possibilità di stampare la cosa sbagliata alla fine dell'output (ad esempio poteva stampare un "null" che non dovrebbe essere lì). Oggi ho avuto un po' di tempo per dargli un'occhiata e risolverlo. Ho anche ottimizzato una chiamata a strlen()
che gli ha dato un altro leggero aumento delle prestazioni.