Moje testování ukázalo, že sed
se na něčem takovém může docela snadno stát CPU vázáno. Pokud máte vícejádrový počítač, můžete zkusit vytvořit několik sed
procesy se skriptem, který vypadá asi takto:
#!/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
Zkuste změnit první dva řádky na:
s/[ \t]*|[ \t]*/|/g
To nejlepší, co jsem se sedem dokázal udělat, byl tento scénář:
s/[\s\t]*|[\s\t]*/|/g
s/[\s\t]*$//
s/^|/null|/
V mých testech to běželo asi o 30 % rychleji než váš skript sed. Zvýšení výkonu pochází z kombinace prvních dvou regulárních genů a vynechání příznaku „g“ tam, kde to není potřeba.
O 30 % rychlejší je však jen mírné zlepšení (spuštění výše uvedeného skriptu na vašem 1GB datovém souboru by stále mělo trvat asi hodinu a půl). Chtěl jsem zjistit, jestli bych mohl udělat něco lepšího.
Nakonec žádná jiná metoda, kterou jsem zkoušel (awk, perl a další přístupy se sed), nedopadla lépe, kromě -- samozřejmě -- obyčejné implementace v C. Jak by se dalo očekávat u C, kód je pro zveřejňování zde trochu podrobný, ale pokud chcete program, který bude pravděpodobně rychlejší než jakákoli jiná metoda, můžete se na něj podívat.
V mých testech implementace C skončí asi za 20 % času, který zabere váš skript sed. Takže spuštění na vašem Unixovém serveru může trvat asi 25 minut.
Optimalizací implementace C jsem moc času nestrávil. Není pochyb o tom, že existuje řada míst, kde by se dal algoritmus vylepšit, ale upřímně řečeno, nevím, jestli je možné holit značnou dobu nad rámec toho, čeho již dosahuje. Pokud něco, myslím, že to určitě stanoví horní hranici toho, jaký druh výkonu můžete očekávat od jiných metod (sed, awk, perl, python atd.).
Upravit: Původní verze měla drobnou chybu, která způsobila, že na konci výstupu možná vytiskla špatnou věc (např. mohla vytisknout „null“, která by tam neměla být). Dnes jsem měl čas se na to podívat a opravit to. Také jsem optimalizoval volání na strlen()
což mu dalo další mírné zvýšení výkonu.