GNU/Linux >> Linux Esercitazione >  >> Linux

Contare le righe in file di grandi dimensioni

Su un server multi-core, usa GNU parallel per contare le righe dei file in parallelo. Dopo la stampa del conteggio di ogni riga di file, bc somma tutti i conteggi di riga.

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

Per risparmiare spazio, puoi persino mantenere tutti i file compressi. La riga seguente decomprime ogni file e conta le sue righe in parallelo, quindi somma tutti i conteggi.

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

Come da mio test, posso verificare che Spark-Shell (basato su Scala) è molto più veloce degli altri strumenti (GREP, SED, AWK, PERL, WC). Ecco il risultato del test che ho eseguito su un file che aveva 23782409 righe

time grep -c $ my_file.txt;

reale 0m44.96sutente 0m41.59ssys 0m3.09s

time wc -l my_file.txt;

reale 0m37.57sutente 0m33.48ssys 0m3.97s

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

reale 0m38.22sutente 0m28.05ssys 0m10.14s

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

reale 0m23.38sutente 0m20.19ssys 0m3.11s

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

reale 0m19.90sutente 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


Il tuo fattore di velocità limitante è la velocità I/O del tuo dispositivo di archiviazione, quindi cambiare tra semplici newline/programmi di conteggio pattern non aiuterà, perché è probabile che la differenza di velocità di esecuzione tra questi programmi venga soppressa dal modo più lento disco/archiviazione/ qualunque cosa tu abbia.

Ma se hai lo stesso file copiato su dischi/dispositivi o il file è distribuito tra quei dischi, puoi sicuramente eseguire l'operazione in parallelo. Non conosco specificamente questo Hadoop, ma supponendo che tu possa leggere un file da 10 GB da 4 posizioni diverse, puoi eseguire 4 diversi processi di conteggio delle righe, ciascuno in una parte del file, e sommare i loro risultati:

$ 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 &

Nota il & ad ogni riga di comando, quindi tutto funzionerà in parallelo; dd funziona come cat qui, ma permetteteci di specificare quanti byte leggere (count * bs byte) e quanti saltare all'inizio dell'input (skip * bs byte). Funziona a blocchi, da qui la necessità di specificare bs come dimensione del blocco. In questo esempio, ho partizionato il file da 10 Gb in 4 blocchi uguali di 4 Kb * 655360 =2684354560 byte =2,5 GB, uno dato a ciascun lavoro, potresti voler impostare uno script per farlo per te in base alla dimensione del file e il numero di lavori paralleli che verranno eseguiti. Devi anche sommare il risultato delle esecuzioni, cosa che non ho fatto per la mia mancanza di capacità di script di shell.

Se il tuo filesystem è abbastanza intelligente da dividere file di grandi dimensioni tra molti dispositivi, come un RAID o un filesystem distribuito o qualcosa del genere, e parallelizzare automaticamente le richieste di I/O che possono essere paralizzate, puoi fare una tale divisione, eseguendo molti lavori paralleli, ma usando lo stesso percorso del file e potresti comunque avere un certo guadagno di velocità.

EDIT:Un'altra idea che mi è venuta in mente è che, se le righe all'interno del file hanno la stessa dimensione, puoi ottenere il numero esatto di righe dividendo la dimensione del file per la dimensione della riga, entrambe in byte. Puoi farlo quasi istantaneamente in un unico lavoro. Se hai la dimensione media e non ti interessa esattamente il conteggio delle linee, ma desideri una stima, puoi eseguire la stessa operazione e ottenere un risultato soddisfacente molto più velocemente dell'operazione esatta.


Prova:sed -n '$=' filename

Anche cat non è necessario:wc -l filename è sufficiente nel tuo modo attuale.


Linux
  1. Contare le righe in un file?

  2. Comando wc Linux

  3. Il filesystem di Linux si sta riempiendo, nonostante non ci siano file o directory di grandi dimensioni

  4. Come contare le righe in un file in UNIX/Linux

  5. Conta le righe di tutti i file nella directory di Ubuntu

Copiare file in Linux

Trova file di grandi dimensioni in Linux

Come dividere file audio di grandi dimensioni su Linux

5 modi per contare il numero di righe in un file

Come scaricare file di grandi dimensioni tramite File Manager

Comando Linux wc – Conteggio di parole, righe, caratteri in un file