Si quieres algo de velocidad real:
echo 'int cache[256],x,y;char buf[4096],letters[]="tacgn-"; int main(){while((x=read(0,buf,sizeof buf))>0)for(y=0;y<x;y++)cache[(unsigned char)buf[y]]++;for(x=0;x<sizeof letters-1;x++)printf("%c: %d\n",letters[x],cache[letters[x]]);}' | gcc -w -xc -; ./a.out < file; rm a.out;
Es un pseudo-one-liner increíblemente rápido.
Una prueba simple muestra que en mi Core i7 CPU 870 @ 2.93GHz cuenta con poco más de 600MB / s:
$ du -h bigdna
1.1G bigdna
time ./a.out < bigdna
t: 178977308
a: 178958411
c: 178958823
g: 178947772
n: 178959673
-: 178939837
real 0m1.718s
user 0m1.539s
sys 0m0.171s
A diferencia de las soluciones que involucran la clasificación, esta se ejecuta en memoria constante (4K), lo cual es muy útil si su archivo es mucho más grande que su memoria RAM.
Y, por supuesto, con un poco de grasa en el codo, podemos reducir 0,7 segundos:
echo 'int cache[256],x,buf[4096],*bp,*ep;char letters[]="tacgn-"; int main(){while((ep=buf+(read(0,buf,sizeof buf)/sizeof(int)))>buf)for(bp=buf;bp<ep;bp++){cache[(*bp)&0xff]++;cache[(*bp>>8)&0xff]++;cache[(*bp>>16)&0xff]++;cache[(*bp>>24)&0xff]++;}for(x=0;x<sizeof letters-1;x++)printf("%c: %d\n",letters[x],cache[letters[x]]);}' | gcc -O2 -xc -; ./a.out < file; rm a.out;
Las redes de poco más de 1.1GB / s terminan en:
real 0m0.943s
user 0m0.798s
sys 0m0.134s
A modo de comparación, probé algunas de las otras soluciones en esta página que parecían tener algún tipo de promesa de velocidad.
La solución sed
/ awk
hizo un valiente esfuerzo, pero murió después de 30 segundos. Con una expresión regular tan simple, espero que esto sea un error en sed (GNU sed versión 4.2.1):
$ time sed 's/./&\n/g' bigdna | awk '!/^$/{a[$0]++}END{for (i in a)print i,a[i];}'
sed: couldn't re-allocate memory
real 0m31.326s
user 0m21.696s
sys 0m2.111s
El método perl también parecía prometedor, pero me di por vencido después de ejecutarlo durante 7 minutos.
time perl -e 'while (<>) {$c{$&}++ while /./g} print "$c{$_} $_\n" for keys %c' < bigdna
^C
real 7m44.161s
user 4m53.941s
sys 2m35.593s