定期的に実行するシェルスクリプトがあり、その次の部分が遅くなります。
grep -v -f RemoveTheseGoodIPs.txt FromTheseShadyIPs.txt > RemainingBadIPs.txt
効果がある出力を提供するのに156秒しかかかりません。私は理解しやすく、エレガントなこのタスクを実行するためのより速い方法を見つけたいと思います。
コンテキスト:「FromTheseShadyIPs.txt」は200,000個の疑わしいIPアドレスのリストであり、「RemoveTheseGoodIPs.txt」は3,000個の良好なIPで構成されるホワイトリストファイルです。最後に、外部ファイアウォールが参照できるブラックリストを作成しましたが、3,000個の良好なIPがブラックリストに表示されることは望ましくありません。役に立つ場合、両方のファイルのIP順序は重要ではなく、すでに各ファイルから重複排除されています。処理サーバーはまともな仕様のDebian 9を実行しています。
答え1
そのオプションを追加してみてください-F
。正規表現処理を行わずに入力を文字列リテラルとして解釈します。
答え2
スクリプトには実行速度よりも重要な問題があり、次の2つの方法で矛盾が発生します。
- 正規表現と文字列:文字列比較を使用する必要がありますが、正規表現比較を使用しています。作成したとおり、
.
RemoveTheseGoodIPs.txtのIPアドレスのsは、FromTheseShadyIPs.txtのすべての文字と一致します。 - 部分対全体:全体行比較を使用する必要がありますが、部分行比較を使用しています。作成したとおり、RemoveTheseGoodIPs.txtの短いIPアドレスは、FromTheseShadyIPs.txtの対応するアドレスを含むすべてのIPアドレスと一致します。
これを考慮すると、現在のスクリプトはRemoveTheseGoodIPs.txtに存在しないIPアドレスをFromTheseShadyIPs.txtからほぼ確実に削除し、ファイアウォールを効果的に破壊します。
たとえば、RemoveTheseGoodIPs.txtを含め1.2.3.4
てFromTheseShadyIPs.txtを含めると、911.253.456.789
必要な完全な行文字列一致ではなく部分行正規表現一致が実行されるため、grepは2番目のIPアドレスを削除します。
$ head RemoveTheseGoodIPs.txt FromTheseShadyIPs.txt
==> RemoveTheseGoodIPs.txt <==
1.2.3.4
==> FromTheseShadyIPs.txt <==
9.8.7.6
911.253.456.789
6.7.8.9
$ grep -v -f RemoveTheseGoodIPs.txt FromTheseShadyIPs.txt
9.8.7.6
6.7.8.9
使用する必要があります
$ grep -vFxf RemoveTheseGoodIPs.txt FromTheseShadyIPs.txt
9.8.7.6
911.253.456.789
6.7.8.9
スクリプトを動作させます。これは-F
正規表現比較ではなく文字列のためのものであり、部分比較では-x
なく行全体のものです。これは現在のスクリプトよりも速いかもしれませんが、より重要な違いは強く機能することです。
grepがこれらのオプションをサポートしていないため、サポートされているバージョンを取得できない場合は、awkで次のものを使用できます。
$ awk 'NR==FNR{a[$0]; next} !($0 in a)' RemoveTheseGoodIPs.txt FromTheseShadyIPs.txt
9.8.7.6
911.253.456.789
6.7.8.9
〜のようにコメントに@Paul_Pedantが言及されました。それにもかかわらず、grepとawkの実装によっては、awkを使用する方がgrepより速くなる可能性があります。