巨大なテキストファイルで「head」または「tail」を使用する-19 GB


14

非常に大きなテキストファイルのチャンクの表示に問題があります。約19 GBのこのファイルは、明らかに大きすぎて従来の方法では表示できません。

私が試してみましたhead 1tail 1head -n 1tail -n 1)両方のコマンドと運で(真ん中の部分で取得する)、さまざまな方法で一緒にパイプ。Ubuntu 9.10を実行しているLinuxマシンはこのファイルを処理できません。

このファイルをどのように処理しますか?私の最終的な目標は、45000000行と45000100行に磨きをかけることです。


簡単なPythonスクリプトを記述して行を読み取り、ファイルに必要な行を印刷することを考えていますが、これには長い時間がかかることを想像できます
...-nicorellius

すべての線は同じ長さですか?
ポール

@Paul-残念ながら、それらは同じ長さではありません。
nicorellius

split大きなファイルを扱いやすくすることができます。
iglvzx

1
OK。大きなファイルの処理には時間がかかるため、以下の回答が役立ちます。探している部分だけを抽出したい場合は、おおよその位置を見積もることができますdd。たとえばdd if=bigfile of=extractfile bs=1M skip=10240 count=5、10GBポイントから始まるファイルから5MBを抽出します。
ポール

回答:


11

を使用する必要がありますsed

sed -n -e 45000000,45000100p -e 45000101q bigfile > savedlines

これはsed、行45000000〜45000100を含めて印刷し、行45000101で終了するように指示します。


1
まだ-45000000,45000100p bigfileのように非常に遅いです。テール-100> savedlines
ドミトリーポーシュキン

tail+|head10〜15%速くなります。
エーリッヒ

4

単一のフィールドを持つ単一のテーブルでMySQLデータベースを作成します。次に、ファイルをデータベースにインポートします。これにより、特定の行を簡単に検索できます。

他の何かがもっと速くなるとは思わない(すでに失敗headtailている場合)。最終的に、行を検索するアプリケーションは、改行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つの大きな利点は、後で別の行セットを抽出することに決めた場合、処理を再度何時間も待つ必要がないことです(もちろんデータベースを削除しない限り)。


したがって、これは確かに良い解決策です。sed以下のコマンドで動作するようにし、私の行を特定しました。しかし、今、私はデータベースの方法がより適しているかもしれないというフォローアップの質問があります。ファイルから数百行を削除する必要があります。
-nicorellius

sedもそれができると確信しています。もちろん、データベースにデータがある場合、必要な行だけで新しいファイルをエクスポートするのは簡単です。
デアホッホステープラー

再度、感謝します。私はsed答えを取りました(よりすぐに喜んでくれたので;-)が、将来あなたの方法を使用するので、あなたに賛成票をくれました。それは有り難いです。
-nicorellius

1
行にa FIELDS TERMINATED BY '\n'を追加してみてくださいLOAD DATA
デアホッホステープラー

1
申し訳ありませんが、コードに誤りがありました。また、あなたのケースに正しい構文を追加しました(今回テストしました)。
デアホッホステープラー

1

大きなファイルのための二つの古き良きツールがあるjoinsplit--lines=<number>ファイルを特定のサイズの複数のファイルにカットするオプションでsplitを使用できます。

たとえばsplit --lines=45000000 huge_file.txt。結果のパーツはxa、xbなどになります。その後、必要な行を含むheadパーツxbを作成できます。ファイルを「結合」して単一の大きなファイルに戻すこともできます。


素晴らしい、ありがとう、私はsplitコマンドを完全に忘れていました。
Siliconrockstar

0

適切なツールを使用していますが、それらを誤って使用しています。前にU&Lで回答したようにtail -n +X file | head -n Y(Xで始まるY行+よりも10〜15%高速です)sed。また、のように明示的exitにプロセスを明示的に行う必要はありませんsed

tailは最初のX-1行を読み取って破棄し(その方法はありません)、次の行を読み取って出力します。headは要求された行数を読み取って出力し、終了します。headが終了すると、tailはSIGPIPEシグナルを受信して​​終了するため、入力ファイルからバッファサイズ相当(通常は数キロバイト)以上の行を読み取ることはありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.