列値に基づいてCSVファイルから行を削除する

列値に基づいてCSVファイルから行を削除する

次の形式の1,200万行を含むCSVファイルがあります。

mcu_i,INIT,200,iFlash,  11593925,     88347,,0x00092684,r,0x4606b570,   ok,,         32,single,op-c,0,,         0,         0,         0,
mcu_i,INIT,200,iFlash,  11593931,     88348,,0x00092678,r,0x28003801,   ok,,         32,single,op-c,0,,         0,         0,         0,

次のロジックを使用して、6番目の列の値に基づいて行を削除したいと思います。 if (value >= X AND value <= Y ) => 行の削除

gawkを使って解決策を見つけました。

gawk -i inplace -F ',' -v s="$start_marker" -v e="$end_marker" '!($6 <= e && $6 >= s)' myfile.csv

しかし、時間がかかりすぎるので、より良いパフォーマンスを持つ他のソリューションが欲しいです。

ありがとう

ベストアンサー1

長い話を短く

標準出力をgawkリダイレクト/dev/nullまたはパイピングすると、速度がcat大幅に向上し、実行時間が大幅に短縮されます。

gawk -i inplace [...] myfile.csv >/dev/null

または:

gawk -i inplace [...] myfile.csv | cat

水に飛び込む

@RomeoNinovの場合でも回答元のコマンドよりも実際に速く実行されます。説明したいです。なぜを使用しても高速です-i inplace

見たら対話型および非対話型バッファリング部分的にgawk 情報ページ、次の内容が表示されます。

インタラクティブプログラムは平均レベルです。ラインバッファ出力します(つまり、各行を作成します)。非対話型プログラムは、バッファがいっぱいになるまで待ちます。これは複数行の出力にすることができます。

gawk結果が一部の「in-place」で印刷されても標準出力として印刷されない場合も同様です。

はい

10行のファイルがあります。

$ cat somefile
1
2
3
4
5
6
7
8
9
10

デフォルトでは(ファイルを変更せずにすべての行をそのまま印刷します)、10回のstraceシステムコールが実行されます(ソースファイルの各行に1つずつ)。gawkwrite

$ strace -e trace=write -c gawk -i inplace 1 somefile 
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00    0.000098           9        10           write
------ ----------- ----------- --------- --------- ----------------
100.00    0.000098           9        10           total

これは対話的に実行され、結果が次のようになるためです。ラインバッファgawk結果が標準出力ではなくファイルに書き込まれても、各行は完了するとすぐに印刷されます。)

stdoutを非対話型にするためにコマンドにリダイレクト/dev/null(またはパイプで接続)すると、単一のシステム呼び出しのみが呼び出されるように見えます。これは、すべての行をすぐに印刷せず、バッファがいっぱいになった場合にのみ結果をフラッシュするためです。catstracegawkwrite

$ strace -e trace=write -c gawk -i inplace 1 somefile > /dev/null
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00    0.000020          20         1           write
------ ----------- ----------- --------- --------- ----------------
100.00    0.000020          20         1           total

もちろん、これは累積的であり、入力ファイルが大きいほど、対話型実行と非対話型実行との差が大きくなります。

一般化する

gawk対話モードでは、処理が完了すると各行がファイルに書き込まれるため、コマンドは遅くなります。これは、ファイルに何百万回もの書き込みを行うことを意味します。

@RomeoNinovのソリューションは使用しないため、元のコマンドよりも高速ですが、出力を一時ファイルにリダイレクトするため、inplace非対話型モードで実行され、バッファフラッシュを最適化し、ファイルgawk操作の書き込み操作を少なくします。

しかし、質問に提供されたコマンドは引き続き使用できますが、stdoutを/dev/null(とにかく空にするため)リダイレクトまたはパイプするとcatすぐに実行されます。

gawk次のように使用する場合のセキュリティリスクinplace

私は自分の仕事でうまくいくと予測不可能な結果を​​もたらす可能性があるという@RomeoNinovのコメントに全く同意しませんが、@OlivierDulacのコメント-i inplaceこれは、一般的な使用がセキュリティの脆弱性と見なされる理由を説明する便利な答えを提供します。この問題を解決する方法安全な方法で実行してください。

おすすめ記事