比较 awk 与 grep

比较 awk 与 grep

我已经针对非常大的文件运行了以下两个命令

grep -E 'string1|string2' 151103*.log|grep 'string3' | grep string4

awk '/string1|string2/ && /string3/ && /string4/' 151103*.log

执行时间几乎相同。但awk更快地向我展示了匹配的结果。grep也向我展示了相同的结果,但最后,当过程完成时。

两个过程花费的时间相同,只是想知道搜索awk和背后的逻辑grep

为什么awk更快?这两个程序有不同的搜索逻辑吗?如果我在上面的搜索中混淆了字符串怎么办,这会对搜索速度产生影响吗?

答案1

GNUgrep缓冲输出,但 GNUawk不缓冲。即使您没有使用 GNUawk并且正在使用其他一些变体,如果您打印到终端,它可能仍然是行缓冲的,因此会刷新每个出现的\newline 的输出,但您grep写入管道,因此会阻塞 -无论如何缓冲。如果您有 GNU,grep您可以使用grep --line-buffered ... | grep ...它进行比较以尽快看到结果。可能grep会在几乎任何比赛测试中击败awk——尤其是 GNU grep

sed也是做你想做的事情:

sed -ne'/string4/{/string3/s/string[12]/&/p;}' <in >out

答案2

grep 管道在 string4 的最后一个匹配某些内容之前无法输出任何内容grep,并且只有在前一个管道缓冲区填满后才获取输入。查看相关问题管道缓冲区有多大?关闭管道中的缓冲

根据输入中字符串的频率,通过将静态搜索放在第一位,您可以看到运行时的差异,从而减少扩展正则表达式的查看次数。

答案3

您的 awk 示例一次性完成整个正则表达式搜索。对于每一行输入,如果找到第一、第二和第三个正则表达式,则将打印该行,并且您将立即看到输出(在处理匹配行时)。

您的 grep 示例使用 3 个不同的 grep 调用(每个正则表达式一个)来执行相同的操作,但每个调用的输出都将成为下一个调用的输入,这意味着每个调用都需要在下一个调用需要处理之前完成。

如果您有一个 1000 行文件,并且只有第 5 行与所有三个正则表达式匹配,则 awk 命令将在处理第 5 行之后、处理第 6 行之前为您提供输出。将其与管道 grep 语句进行比较。 grep 的第一次调用将找到第 5 行以及可能与第一个正则表达式匹配的任何其他行,并且在处理输入的第 1000 行(最后)行后,其输出将成为 grep 的第二次调用的输入。 grep 的第二次调用会处理第一个输出的多少行,并输出与第一个和第二个正则表达式匹配的行,然后这些行将成为 grep 第三次调用的输入。当第三次调用 grep 处理每一行时,它将输出与其正则表达式匹配的任何行。

您可以比较上面示例中 grep 的最佳和最差情况:如果除了第 5 行(匹配所有 5 行)之外,没有任何行与任何正则表达式匹配,则第一个 grep 处理 1000 行,第二个 grep 处理 1 行,并且第三个 grep 处理 1 行:它将在产生任何输出之前处理 1002 行(最好情况)。如果所有行都与前两个正则表达式匹配,但只有一行与第三个正则表达式匹配,则管道 grep 构造将处理 1000 + 1000 行 + 5 = 2005 行,然后才能找到第 5 行的匹配项并产生一些输出(它将继续处理第二个 grep 输出中剩余的 995 行,但您不会看到更多输出,因为没有其他内容匹配)。

将其与 awk 命令进行比较,该命令同时检查每行的所有三个正则表达式,并在处理第 5 行后给出输出。当您同时检查更多文件时,差异会更大。

例如,比较一下您是否会看到更快的输出,而不是像上面那样同时在所有文件上运行 grep 命令(理论上,您应该这样做,但结果可能会根据整个文件中的命中分布而有所不同):

grep -E 'string1|string2' 151103*.log|grep 'string3' | grep string4

您可以单独对每个文件运行一系列 grep 命令,如下所示:

for i in 151103*.log; 
  do grep -E 'string1|string2' $i |grep 'string3' | grep string4; 
done

这仍然不会像 awk 语句那样快速生成输出,但您可能会看到差异。

答案4

虽然 grep 、 awk 和 sed 可用于类似的任务,但每个都有其优点和缺点。

Awk 最适合表格数据或需要执行计算等时。

Sed 擅长替换文本。

Grep 最好从输入数据中选择行,因此我希望它比 awk 更快地完成此任务。也许如果您将 3 个 grep 命令合并为一个,您就会看到这样的结果。现在 grep 处于劣势,因为它需要启动 3 次,第二次和第三次需要等待第一次的输入。这也许可以解释为什么结果会延迟。虽然我对此并不确定。

相关内容