非常に大きなファイルのテキストをすばやく置き換える


25

数行で文字列を置き換える必要がある25GBのテキストファイルがあります。私は問題なく使用できますsedが、実行には本当に長い時間がかかります。

sed -i 's|old text|new text|g' gigantic_file.sql

これを行う簡単な方法はありますか?


置換するテキストがある行番号を知っていますか?高速化するための唯一のオプションではない場合は、より高速なコンピューターを入手することです。大量のデータがあるということは、そのデータを検索するのに長時間かかることを意味します。
デビッドキング

行番号をかなりすばやくgrepできるので、はい。
eisaacson

複数のCPUコアを使用して速度を上げることもできます-rankfocus.com/use-cpu-cores-linux-commands
ahaswer

大きなファイルにはsedを使用しないでください。代わりにviまたはvimを見てください。
MikeJRamsey56

回答:


26

あなたが試すことができます:

sed -i '/old text/ s//new text/g' gigantic_file.sql

この参照から:

速度の最適化:実行速度を大きくする必要がある場合(大きな入力ファイルまたは遅いプロセッサまたはハードディスクのため)、「s /.../」を指定する前に「find」式を指定すると、置換がより迅速に実行されます。 ../ "命令。

10Gファイルでの比較を次に示します。前:

$ time sed -i 's/original/ketan/g' wiki10gb
real    5m14.823s
user    1m42.732s
sys     1m51.123s

後:

$ time sed -i '/ketan/ s//original/g' wiki10gb
real    4m33.141s
user    1m20.940s
sys     1m44.451s

最後のsedつづりが間違っています。私は最後の修正するために、昨日、この記事を編集しsedなければなりませんコマンドtime sed -i '/original/ s//ketan/g' wiki10gbとされていませんtime sed -i '/ketan/ s//original/g' wiki10gb。今日は編集を元に戻しています。1。時間がコマンドと一致しなくなったため。2. 3GB以上のファイルでGNU sedを使用して同じテストを行ったため、2つのsed選択肢に違いは見られません。時間の違いはスペルミスによるものだと思います。
-xhienne

@xhienneスペルミスの意味がわかりません。最初の実行では、「オリジナル」という単語を「ケタン」に置き換え、2番目の単語では「ケタン」という用語を「オリジナル」という単語に置き換え、どちらの場合も同じ数の置換を行います。
mkc

1
評判が不十分な新規ユーザーから報告された「修正」を適用していました。今、私はあなたがしたことを理解しています。ただし、ある構文が他の構文よりも優れていることを証明したい場合は、ここでは当てはまらないまったく同じ操作を行う必要があります(CPUごとに、5文字の文字列を検索することは、 7文字の文字列)。さらに、10GBファイルでのこの種のテストは、マシンの負荷(CPU、ディスク)に大きく依存しています。私はtime個人的に結果に多くの変動を見ましたが、全体として、時間の差はありませんでした。
xhienne

私はこれが関連していると信じています-ここで受け入れられた答えを参照してください、stackoverflow.com / questions / 11145270 /… >> sedはファイル全体をストリームしますが、この答えに記載されているように、行番号(既知の場合)を指定すると役立ちます:私の場合、実行速度が2倍に増加しました(GNU sed 4.5)。パターン検索に基づいて、grep -nまたはripgrep(rg)を使用して行番号を見つけることができます。実際には、行番号を指定することは、上記の回答に従って、そのファイルに検索結果を表示するようなものです。
ビクトリアスチュアート

1

短い答えは「いいえ」です。この種の操作の制限要因はディスクIOです。25GBのディスクをより速くストリーミングする方法はありません。編集をsedインプレースせずに、結果を別のドライブに書き込むと(使用可能なドライブがある場合)、少し改善される可能性があります。結果として競合が少なくなります。

あなたは可能性がある(私はかなり確信してあなたがこれを行うことができますよので、Perlを使用して、たとえば-行ごとに正規表現エンジンを使用していないことで少しそれをスピードアップすることができるsedが、私は、構文を知らない) -これはから始まります10,000行目以降。

perl -pe '$. > 10_000 && s/old_text/new_text/g' 

また、RE(メタキャラクター)に何らかの複雑な問題がある場合、それらを最小化すると、正規表現エンジンの効率がわずかに向上します。


1
sedではsed -i '10000,$ s/old_text/new_text/g'
Dani_l

素敵。私はどのようにsed比較するのかわかりません-私はわずかに速いと仮定しますが、ファイルサイズのためにそれほどではありません。
ソブリク

perlはsedよりも速いと思いますが、sedはやや謎めいたものであるか、初期学習曲線の必要性が少なくなります。
-Dani_l

1
今私が言っているだろう、反対を参照してください-あなたは(ほとんど)書き込み可能sedperl、後者はまた、あなたがあまりにもスクリプトVERBOSE以上書くことができます。
-Sobrique

0

新しいテキストと古いテキストの長さが同じ場合、ファイル全体をコピーする代わりに、ファイルを検索して変更されたバイトのみを書き込むことができます。そうしないと、大量のデータを移動することに縛られてしまいます。

注:これには注意が必要であり、カスタムコードの記述が必要です。

CまたはC ++で作業している場合は、fseekのマニュアルページを参照するか、システムコールのシークおよび書き込み用の言語ラッパーを参照してください。

コマンドラインのみの使用を主張し、テキストのバイトオフセットを取得できる場合は、慎重に記述された「dd」コマンドを使用して、置換テキストを所定の場所に書き込むことができます。

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