某些命令或脚本能否比 grep 更快地从一个文件中减去另一个文件中的行?

某些命令或脚本能否比 grep 更快地从一个文件中减去另一个文件中的行?

我有一个定期运行的 shell 脚本,它的以下部分会导致速度变慢。

grep -v -f RemoveTheseGoodIPs.txt FromTheseShadyIPs.txt > RemainingBadIPs.txt

有用。只需 156 秒即可给出输出。我希望找到一种更快的处理方法,同时又易于理解且优雅。

对于上下文:“FromTheseShadyIPs.txt”是 200k 可疑 IP 地址的列表,“RemoveTheseGoodIPs.txt”是 3k 良好 IP 的白名单文件。最终,我生成了一个黑名单,我的外部防火墙可以参考,但我不希望我的 3k 良好 IP 出现在我的黑名单中。如果有帮助,两个文件中 IP 的顺序并不重要,并且它们已经在每个文件中进行了重复数据删除。处理服务器在不错的规格上运行 Debian 9。

答案1

尝试添加该-F选项。它不执行任何正则表达式处理,只是将输入解释为字符串文字。

答案2

您的脚本存在比执行速度更重要的问题,它还会以两种方式遇到错误匹配:

  1. 正则表达式与字符串:当您应该使用字符串比较时,您正在使用正则表达式比较。正如所写,.RemoveTheseGoodIPs.txt 中的 IP 地址中的 s 将匹配 FromTheseShadyIPs.txt 中的任何字符,并且
  2. 部分与完整:当您应该使用全行比较时,您正在使用部分行比较。正如所写,RemoveTheseGoodIPs.txt 中较短的 IP 地址将与 FromTheseShadyIPs.txt 中包含该地址的任何 IP 地址匹配

鉴于此,您当前的脚本几乎肯定会从 FromTheseShadyIPs.txt 中删除RemoveTheseGoodIPs.txt 中不存在的 IP 地址,从而有效地破坏您的防火墙。

例如,如果包含RemoveTheseGoodIPs.txt1.2.3.4并包含FromTheseShadyIPs.txt 911.253.456.789,那么您的grep将删除第二个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 在评论中提到无论如何,使用 awk 可能比 grep 更快,具体取决于您的 grep 和 awk 实现。

相关内容