Dを除くすべての行を削除

Dを除くすべての行を削除

次の詳細を含む3つの大きなファイルがあるシーンがありますTest.txtTest1.txtTest2.txt

H|||||||||||||||||||||||
D||||||||||||||||||||||||
D|||||||||||||||||||||||
H|||||||||||||||||||||
D||||||||||||||||||||||||
D||||||||||||||||||||||||
T||||||||||||||||||||||||

Dラインを除くすべてのアイテムを削除する必要があります。私の3つのファイルすべてでは、次のようになります。 (10GB以上)

D||||||||||||||||||||||||
D|||||||||||||||||||||||
D||||||||||||||||||||||||
D||||||||||||||||||||||||

Test.txtしたがって、 、Test2.txt、 で D 行だけを保持した後、Test3.txt新しいファイルにマージする必要があります。

私はsedを使って上記のことをしました。

sed '/^\('D'\)|/!d' $Filename.txt >>  $NewFilename.txt

しかし、ファイルが大きいので時間がかかります。

これを効率的に実行するために使用できる他のコマンドはありますか?

答え1

cat Test.txt Test2.txt Test3.txt | LC_ALL=C grep '^D' > newfile.txt

または:

for file in Test.txt Test2.txt Test3.txt; do
  LC_ALL=C grep '^D' < "$file"
done > newfile.txt

または、grepお気に入りのGNUがgrepその-hオプションをサポートしている場合(ファイル名の印刷を避けるため):

LC_ALL=C grep -h '^D' Test.txt Test2.txt Test3.txt > newfile.txt

これにより、UTF-8データの解析を回避LC_ALL=Cできます。grepを使用すると、^D各行grepの最初の文字のみが表示されます。grep、特にgrepGNUは一般的にsed

答え2

これはCPUバインディングではなくI / Oバインディング操作である可能性が高いため、次の正規表現エンジンを使用しなくても次のようになります。

grep -F 'D|' Test.txt Test2.txt Test3.txt

ファイルを線で表示した後にパターンを検索する必要があるため、時間がかかります。

これがワンタイムでエンコーディングを気にしない場合は、mmap(3)ファイル全体をメモリに入れて次のように使用できますmemmem(3)

char *p;
if ((p = memmem(file, size, "\nD|", 3)) != NULL) {
        /* massage the line, i.e. find the next '\n'
         * and print the region between p+1 and the
         * next '\n' */
}

どこにfileマップされたバッファへのポインタであり、sizeファイルサイズです。 (お手伝いになれば詳しく説明させていただきます。)

このアプローチはまだ時間がかかりますが(問題がI / Oバインドされているため)、少なくともファイルを行として表示する時間を節約できます。

関連情報