非常に大きなテキストファイルのチャンクの表示に問題があります。このファイルは約19GBですが、明らかに大きすぎて従来の方法では表示できません。
私が試してみました head 1
およびtail 1
(head -n 1
およびtail -n 1
)両方のコマンドをさまざまな方法でパイプでつなぎます(途中でピースを取得するため)。 Ubuntu 9.10を実行しているLinuxマシンでこのファイルを処理できません。
このファイルをどのように処理しますか?私の最終的な目標は、行45000000と45000100に焦点を当てることです。
sed
を使用する必要があります。
sed -n -e 45000000,45000100p -e 45000101q bigfile > savedlines
これは、sed
に45000000-45000100行を含めて印刷し、45000101行で終了するように指示します。
単一のフィールドを持つ単一のテーブルを使用してMySQLデータベースを作成します。次に、ファイルをデータベースにインポートします。これにより、特定の行を非常に簡単に検索できます。
他に何も速くなるとは思えません(head
とtail
がすでに失敗している場合)。結局、行n
を見つけたいアプリケーションは、n
改行が見つかるまでファイル全体を検索する必要があります。ある種のルックアップ(ファイルへのラインインデックスからバイトオフセット)がなければ、これ以上のパフォーマンスは達成できません。
MySQLデータベースを作成してデータをインポートするのがいかに簡単かを考えると、これは実行可能なアプローチだと思います。
これを行う方法は次のとおりです。
DROP DATABASE IF EXISTS helperDb;
CREATE DATABASE `helperDb`;
CREATE TABLE `helperDb`.`helperTable`( `lineIndex` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `lineContent` MEDIUMTEXT , PRIMARY KEY (`lineIndex`) );
LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable (lineContent);
SELECT lineContent FROM helperTable WHERE ( lineIndex > 45000000 AND lineIndex < 45000100 );
/tmp/my_large_file
は、読み取りたいファイルです。
各行にタブ区切りの値を持つファイルをインポートするための正しい構文は次のとおりです。
LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable FIELDS TERMINATED BY '\n' (lineContent);
これのもう1つの大きな利点は、後で別の行のセットを抽出することにした場合、(もちろんデータベースを削除しない限り)処理を再度待つ必要がないことです。
大きなファイル用の2つの古き良きツールは、join
とsplit
です。 split with --lines=<number>
オプションを使用して、ファイルを特定のサイズの複数のファイルにカットできます。
たとえば、split --lines=45000000 huge_file.txt
。結果のパーツはxa、xbなどになります。次に、パーツをhead
することができますxbこれには必要な行が含まれます。ファイルを「結合」して単一の大きなファイルに戻すこともできます。
あなたは適切なツールを持っていますが、それらを誤って使用しています。以前のように 回答済み U&Lで、tail -n +X file | head -n Y
(+
に注意)は、Xで始まるY行のsed
よりも10〜15%高速です。 、exit
のように、プロセスを明示的にsed
する必要はありません。
tailは最初のX-1行を読み取って破棄し(それを回避する方法はありません)、次の行を読み取って出力します。 headは、要求された行数を読み取って出力し、終了します。ヘッドが終了すると、テールはSIGPIPE信号を受信して停止するため、入力ファイルからバッファーサイズに相当する(通常は数キロバイト)行を超えて読み取ることはありません。