GNU/Linux >> Tutoriales Linux >  >> Linux

Contar líneas en archivos grandes

En un servidor multinúcleo, utilice GNU paralelo para contar las líneas de archivo en paralelo. Después de imprimir el recuento de líneas de cada archivo, bc suma todos los recuentos de líneas.

find . -name '*.txt' | parallel 'wc -l {}' 2>/dev/null | paste -sd+ - | bc

Para ahorrar espacio, incluso puede mantener todos los archivos comprimidos. La siguiente línea descomprime cada archivo y cuenta sus líneas en paralelo, luego suma todas las cuentas.

find . -name '*.xz' | parallel 'xzcat {} | wc -l' 2>/dev/null | paste -sd+ - | bc

Según mi prueba, puedo verificar que Spark-Shell (basado en Scala) es mucho más rápido que las otras herramientas (GREP, SED, AWK, PERL, WC). Aquí está el resultado de la prueba que ejecuté en un archivo que tenía 23782409 líneas

time grep -c $ my_file.txt;

real 0m44.96susuario 0m41.59ssys 0m3.09s

time wc -l my_file.txt;

real 0m37.57susuario 0m33.48ssys 0m3.97s

time sed -n '$=' my_file.txt;

real 0m38.22suser 0m28.05ssys 0m10.14s

time perl -ne 'END { $_=$.;if(!/^[0-9]+$/){$_=0;};print "$_" }' my_file.txt;

real 0m23.38suser 0m20.19ssys 0m3.11s

time awk 'END { print NR }' my_file.txt;

real 0m19.90suser 0m16.76ssys 0m3.12s

spark-shell
import org.joda.time._
val t_start = DateTime.now()
sc.textFile("file://my_file.txt").count()
val t_end = DateTime.now()
new Period(t_start, t_end).toStandardSeconds()

res1:org.joda.time.Seconds =PT15S


Su factor de velocidad limitante es la velocidad de E/S de su dispositivo de almacenamiento, por lo que cambiar entre programas simples de conteo de líneas nuevas/patrones no ayudará, porque es probable que la diferencia de velocidad de ejecución entre esos programas se suprima por la forma en que el disco/almacenamiento/dispositivo es más lento. lo que tengas.

Pero si tiene el mismo archivo copiado en discos/dispositivos, o el archivo está distribuido entre esos discos, ciertamente puede realizar la operación en paralelo. No sé específicamente sobre este Hadoop, pero suponiendo que pueda leer un archivo de 10 gb desde 4 ubicaciones diferentes, puede ejecutar 4 procesos de conteo de líneas diferentes, cada uno en una parte del archivo, y resumir sus resultados:

$ dd bs=4k count=655360 if=/path/to/copy/on/disk/1/file | wc -l &
$ dd bs=4k skip=655360 count=655360 if=/path/to/copy/on/disk/2/file | wc -l &
$ dd bs=4k skip=1310720 count=655360 if=/path/to/copy/on/disk/3/file | wc -l &
$ dd bs=4k skip=1966080 if=/path/to/copy/on/disk/4/file | wc -l &

Observe el & en cada línea de comando, por lo que todo se ejecutará en paralelo; dd funciona como cat aquí, pero nos permite especificar cuántos bytes leer (count * bs bytes) y cuántos omitir al principio de la entrada (skip * bs bytes). Funciona en bloques, de ahí la necesidad de especificar bs como el tamaño del bloque. En este ejemplo, he particionado el archivo de 10 Gb en 4 partes iguales de 4 Kb * 655360 =2684354560 bytes =2,5 GB, uno dado a cada trabajo, es posible que desee configurar un script para que lo haga por usted en función del tamaño del archivo y el número de trabajos paralelos que ejecutará. También debe sumar el resultado de las ejecuciones, lo que no he hecho por mi falta de capacidad de script de shell.

Si su sistema de archivos es lo suficientemente inteligente como para dividir archivos grandes entre muchos dispositivos, como un RAID o un sistema de archivos distribuido o algo así, y paralelizar automáticamente las solicitudes de E/S que se pueden paralelizar, puede hacer esa división, ejecutando muchos trabajos paralelos, pero usando la misma ruta de archivo, y aún puede tener algo de ganancia de velocidad.

EDITAR:Otra idea que se me ocurrió es que, si las líneas dentro del archivo tienen el mismo tamaño, puede obtener el número exacto de líneas dividiendo el tamaño del archivo por el tamaño de la línea, ambos en bytes. Puedes hacerlo casi instantáneamente en un solo trabajo. Si tiene el tamaño medio y no le importa exactamente el número de líneas, pero desea una estimación, puede realizar esta misma operación y obtener un resultado satisfactorio mucho más rápido que la operación exacta.


Prueba:sed -n '$=' filename

También cat es innecesario:wc -l filename es suficiente en tu forma actual.


Linux
  1. Mover archivos en Linux sin mv

  2. El sistema de archivos de Linux se está llenando, a pesar de que no hay archivos o directorios grandes

  3. ¿Cómo contar líneas en un documento?

  4. Usando nc para transferir archivos grandes

  5. ¿Cómo contar el número total de líneas de archivos encontrados?

Copiar archivos en Linux

Encuentra archivos grandes en Linux

Cómo dividir archivos de audio grandes en Linux

5 formas de contar el número de líneas en un archivo

Cómo descargar archivos grandes a través del Administrador de archivos

Comando wc de Linux:recuento de palabras, líneas y caracteres en un archivo