web-dev-qa-db-ja.com

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

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

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

これを行うためのより速い方法はありますか?

27
eisaacson

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

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

これから ref

速度の最適化:実行速度を上げる必要がある場合(入力ファイルが大きいか、プロセッサやハードディスクが遅いため)、 "s /.../。 ../ "命令。

以下は、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
30
mkc

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

あなたmight各行に正規表現エンジンを使用しないことで少しスピードアップできる-たとえば、Perlを使用する(sedでこれを実行できると確信していますが、構文はわかりません)-これは10,000行目から始まります。

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

そして、RE(メタ文字)になんらかの複雑さが存在する場合、それらを最小限に抑えるとわずかに正規表現エンジンの効率が向上します。

1
Sobrique

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

注:これはトリッキーであり、カスタムコードの記述が含まれます。

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

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

0
stolenmoment