2011-07-25 23 views
14

Me preguntaba si hay una manera más eficiente para realizar esta tarea. Estoy trabajando con archivos con un número de líneas que van desde un par de cientos de miles hasta un par de millones. Digamos que sé que las líneas 100,000 - 125,000 son las líneas que contienen los datos que estoy buscando. Me gustaría saber si hay una manera rápida de extraer solo estas líneas deseadas del archivo. En este momento estoy usando un bucle con grep como esto:bash pull ciertas líneas de un archivo

for ((i=$start_fid; i<=$end_fid; i++)) 
    do 
    grep "^$i " fulldbdir_new >> new_dbdir${bscnt} 
    done 

que funciona muy bien es sólo tarda más de lo que me gustaría. Y las líneas contienen más que solo números. Básicamente, cada línea tiene aproximadamente 10 campos; el primero es un entero secuencial que aparece solo una vez por archivo.

Me siento cómodo escribiendo en C si es necesario.

Respuesta

20

sed puede hacer el trabajo ...

sed -n '100000,125000p' input

EDIT: De acuerdo con la sugerencia de Glenn Jackman, se puede ajustar para la eficiencia thusly ...

sed -n '100000,125000p; 125001q' input

+4

agrega un poco de eficiencia con 'sed -n '100000,125000p; 125001q'' –

+0

¡Agradable! Gracias por eso – Costa

+0

Creo que esta respuesta me funcionará, ¿qué significa p y q después de 125000 y 125001, respectivamente? – mike

2

Puede probar una combinación de cola y cabeza para obtener las líneas correctas.

head -n 125000 file_name | tail -n 25001 | grep "^$i " 

No olvide perl either.

perl -ne 'print if $. >= 100000 && $. <= 125000' file_name | grep "^$i " 

o algunos Perl más rápido:

perl -ne 'print if $. >= 100000; exit() if $. >= 100000 && $. <= 125000' | grep "^$i " 

Además, en lugar de un bucle for es posible que desee ver en el uso GNU parallel.

5

que haría uso de awk:

awk 'NR >= 100000; NR == 125000 {exit}' file 

Para grandes números también se puede utilizar la notación E :

awk 'NR >= 1e5; NR == 1.25e5 {exit}' file 

EDIT: sugerencia (cf. comentario) @glenn de Jackman

+3

Ahorre tiempo con 'NR> 125000 {exit}' –

+0

@glenn jackman: v. Buen punto. voy a actualizar – mhyfritz

0

Las respuestas hasta ahora lee las primeras líneas de 100000 y los descarta. Como la E/S de disco a menudo es el factor limitante en estos días, sería bueno tener una solución que no tenga que leer las líneas no deseadas.

Si las primeras 100000 líneas tienen siempre la misma longitud total (aproximadamente), entonces puede calcular qué tan lejos buscar en el archivo para llegar aproximadamente a la línea 100000 y luego leer las siguientes 25000 líneas. Tal vez lea un poco más antes y después para asegurarse de tener todas las 25000 líneas.

Sin embargo, no sabría exactamente en qué línea se encontraba, lo que puede o no ser importante para usted.

asumir la longitud promedio de la línea de los primeros 100000 líneas es 130 entonces se podrían obtener algo como esto:

dd if=the_file skip=130 bs=100000 | head -n 25000 

Usted tendría que tirar la primera línea, ya que es probable que sea sólo la mitad de una línea.

Cuestiones relacionadas