Tengo un archivo (queryids.txt) con una lista de 847 palabras clave para buscar. Tengo que grep de las palabras clave de unos 12 archivos csv enormes (el más grande tiene 2.184.820.000 líneas). Eventualmente lo cargaremos en una base de datos de algún tipo, pero por ahora, solo queremos que ciertas palabras clave sean grep.

Mi comando es:

LC_ALL=C fgrep -f queryids.txt subject.csv

Estoy pensando en escribir un script bash como este:

#!/bin/bash

for f in *.csv
do
    ( echo "Processing $f"
    filename=$(basename "$f")
    filename="${filename%.*}"
    LC_ALL=C fgrep -f queryids.txt $f > $filename"_goi.csv" ) &
done

Y lo ejecutaré usando: nohup bash myscript.sh &

El queryids.txt se ve así:

ENST00000401850
ENST00000249005
ENST00000381278
ENST00000483026
ENST00000465765
ENST00000269080
ENST00000586539
ENST00000588458
ENST00000586292
ENST00000591459

El archivo del asunto se ve así:

target_id,length,eff_length,est_counts,tpm,id
ENST00000619216.1,68,2.65769E1,0.5,0.300188,00065a62-5e18-4223-a884-12fca053a109
ENST00000473358.1,712,5.39477E2,8.26564,0.244474,00065a62-5e18-4223-a884-12fca053a109
ENST00000469289.1,535,3.62675E2,4.82917,0.212463,00065a62-5e18-4223-a884-12fca053a109
ENST00000607096.1,138,1.92013E1,0,0,00065a62-5e18-4223-a884-12fca053a109
ENST00000417324.1,1187,1.01447E3,0,0,00065a62-5e18-4223-a884-12fca053a109

Me preocupa que esto lleve mucho tiempo. ¿Existe una forma más rápida de hacer esto?

¡Gracias!

1
Komal Rathi 11 ago. 2016 a las 21:56

2 respuestas

La mejor respuesta

Algunas cosas que puedo sugerir para mejorar el rendimiento:

  1. No es necesario generar un sub-shell usando ( .. ) &, puede usar llaves { ... } & si es necesario.
  2. Use grep -F (búsqueda de cadena fija o sin expresiones regulares) para hacer que grep se ejecute más rápido
  3. Evite el comando basename y use la manipulación de cadenas bash

Prueba este script:

#!/bin/bash

for f in *.csv; do
    echo "Processing $f"
    filename="${f##*/}"
    LC_ALL=C grep -Ff queryids.txt "$f" > "${filename%.*}_goi.csv"
done

Le sugiero que ejecute esto en un conjunto de datos más pequeño para comparar la ganancia de rendimiento.

2
anubhava 12 ago. 2016 a las 07:01

Podrías probar esto en su lugar:

awk '
BEGIN {
    while ( (getline line < "queryids.txt") > 0  ) {
        re = ( re=="" ? "" : re "|") line
    }
}
FNR==1 { close(out); out=FILENAME; sub(/\.[^.]+$/,"_goi&",out) }
$0 ~ re { print > out }
' *.csv

Está usando una expresión regular en lugar de una comparación de cadenas, ya sea que eso importe o no y, de ser así, lo que podemos hacer al respecto depende de los valores en queryids.txt. De hecho, puede haber una forma mucho más rápida y sólida de hacer esto dependiendo de lo que contengan sus archivos, por lo que si edita su pregunta para incluir algunos ejemplos del contenido de su archivo, podríamos ser de más ayuda.

Veo que ahora ha publicado una entrada de muestra y, de hecho, podemos hacer esto mucho más rápido y de manera más sólida mediante una búsqueda de hash:

awk '
BEGIN {
    FS="."
    while ( (getline line < "queryids.txt") > 0  ) {
        ids[line]
    }
}
FNR==1 { close(out); out=FILENAME; sub(/\.[^.]+$/,"_goi&",out) }
$1 in ids { print > out }
' *.csv
0
Ed Morton 11 ago. 2016 a las 19:39