GNU/Linux >> Linux の 問題 >  >> Linux

大きなファイルの行数を数える

マルチコア サーバーでは、GNU 並列を使用してファイル行を並列にカウントします。各ファイルの行数が出力された後、bc はすべての行数を合計します。

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

容量を節約するために、すべてのファイルを圧縮したままにすることもできます。次の行は、各ファイルを解凍し、その行を並行してカウントしてから、すべてのカウントを合計します。

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

私のテストによると、Spark-Shell (Scala ベース) が他のツール (GREP、SED、AWK、PERL、WC) よりもはるかに高速であることを確認できます。これは、23782409 行のファイルに対して実行したテストの結果です

time grep -c $ my_file.txt;

実 0m44.96suser 0m41.59ssys 0m3.09s

time wc -l my_file.txt;

実 0m37.57suser 0m33.48ssys 0m3.97s

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

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

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

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

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

実 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


制限速度要因はストレージ デバイスの I/O 速度であるため、単純な改行/パターン カウント プログラムを変更しても役に立ちません。これらのプログラム間の実行速度の違いは、ディスク/ストレージ/

ただし、同じファイルを複数のディスク/デバイスにコピーした場合、またはファイルがそれらのディスクに分散されている場合は、確実に操作を並行して実行できます。この Hadoop について具体的にはわかりませんが、4 つの異なる場所から 10 GB のファイルを読み取ることができると仮定すると、4 つの異なる行カウント プロセスをそれぞれファイルの 1 つの部分で実行し、それらの結果を合計できます。

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

& に注意してください 各コマンドラインで、すべてが並行して実行されます。 dd cat のように動作します ただし、読み取るバイト数を指定できるようにします (count * bs バイト) と、入力の先頭でスキップする数 (skip * bs) バイト)。ブロックで動作するため、 bs を指定する必要があります ブロックサイズとして。この例では、10Gb ファイルを 4Kb * 655360 =2684354560 バイト =2.5GB の 4 つの等しいチャンクに分割しました。各ジョブに 1 つ割り当てます。ファイルと、実行する並列ジョブの数。また、実行結果を合計する必要があります。これは、シェル スクリプトの能力がないために私が行っていないことです。

ファイルシステムが、RAID や分散ファイルシステムなどの多くのデバイス間で大きなファイルを分割し、並列化できる I/O 要求を自動的に並列化するのに十分なほどスマートである場合、そのような分割を実行して、多くの並列ジョブを実行できますが、同じファイル パスを使用しても、速度が向上する可能性があります。

EDIT:ファイル内の行が同じサイズの場合、ファイルのサイズを行のサイズで割ることで正確な行数を取得できます。どちらもバイト単位です。 1 つのジョブでほぼ瞬時に実行できます。平均サイズがあり、行数を正確に気にする必要はなく、見積もりが必要な場合は、これと同じ操作を実行して、正確な操作よりもはるかに速く満足のいく結果を得ることができます。


試してみてください:sed -n '$=' filename

猫も不要です:wc -l filename 今のやり方で十分です。


Linux
  1. Linuxでmvなしでファイルを移動する

  2. 大きなファイルやディレクトリがないにもかかわらず、Linux ファイルシステムがいっぱいになっている

  3. UNIX/Linux でファイルの行数を数える方法

  1. ファイルの行数を数えますか?

  2. Ubuntu ディレクトリ内のすべてのファイルの行数を数える

  3. Linux 上の大きなファイルのバイナリ diff/パッチ?

  1. Linuxのファイルから行、単語、文字を数える

  2. Linuxwcコマンド

  3. ドキュメントの行数を数えるには?