【问题标题】:Which is faster? `echo`ing a variable, or `tail`ing a long output file, or maybe `grep`ing the whole thing哪个更快? `echo`ing 一个变量,或者 `tail`ing 一个长的输出文件,或者可能 `grep`ing 整个事情
【发布时间】:2013-04-03 17:29:48
【问题描述】:

我很好奇在以下情况下哪个更快。我有大约 2MB 的输出文件和数千行(我们会说在 15k 到 50k 之间的任何地方)。

我正在寻找文件末尾的字符串(最后 10 行)左右。我多次这样做,有时使用相同的文件的最后 10 行,并且针对多个文件。

我很好奇以下哪个是最快和最有效的:

  1. tail最后10行,保存为变量。当我需要grep 或检查字符串时,echo 那个变量和grep 在输出上
  2. 每次我需要grep 的东西,首先tail 输出文件然后pipegrep 输出
  3. 放弃上述任何一项,每次只需grep 整个文件。

选项 1)

if [ -f "$jobFile".out ]; then
{
  output=$(tail -n 10 "$jobFile".out)
  !((echo "$output" | grep -q "Command exited with non-zero status" ) 
    || (echo "$output" | grep -q "Error termination via Lnk1e")) 
    && continue
  {
    output "$(grep $jobID $curJobsFile)"
    sed -i "/$jobID/d" "$jobIDsWithServer"
  }
fi

选项 2)

if [ -f "$jobFile".out ]; then
{
  !((tail -n 10 "$jobFile".out | grep -q "Command exited with non-zero status" ) 
    || (tail -n 10 "$jobFile".out | grep -q "Error termination via Lnk1e")) 
    && continue
  {
    output "$(grep $jobID $curJobsFile)"
    sed -i "/$jobID/d" "$jobIDsWithServer"
  }
fi

选项 3)

if [ -f "$jobFile".out ]; then
{
  !((grep -q "Command exited with non-zero status" "$jobFile".out) 
    || (grep -q "Error termination via Lnk1e" "$jobFile".out)) 
    && continue
  {
    output "$(grep $jobID $curJobsFile)"
    sed -i "/$jobID/d" "$jobIDsWithServer"
  }
fi

【问题讨论】:

  • Linux 有一个time 命令用于计时命令运行所需的时间。我打赌你可以在这里使用它。
  • 你也可以使用strace之类的东西来查看每个选项调用了哪些IO操作。
  • 大括号和圆括号是怎么回事?在这种情况下,它们不仅不是(全部)必需的,而且显然容易出错(您似乎缺少右括号)。
  • @glennjackman 这是我脚本中的部分复制/部分重写。无论是否需要大括号,它至少有助于提高我的可读性。当然,对于 if 块,它有助于将其与其他所有内容区分开来。不过你是对的,我在这个键入的示例中缺少一个,但在我的实际脚本中却没有。
  • 好的,但请注意大括号和圆括号是不同的:圆括号实际上生成了一个子 shell,而大括号在当前 shell 中执行。所以这个((echo foo) && (echo bar)) 实际上必须完成生成其他 3 个 shell 的工作。

标签: linux performance bash grep tail


【解决方案1】:

选项 2 使用了两次 tail,因此可能会比 1 稍慢。两者都比选项 3 快很多。

你可以做的另一件事是:

if [ -f "$jobFile".out ]; then
{
  !(tac "$jobFile".out | 
    grep -E -m1 -q "(Command exited with non-zero status|Error termination via Lnk1e)")
    && continue
  {
    output "$(grep $jobID $curJobsFile)"
    sed -i "/$jobID/d" "$jobIDsWithServer"
  }
fi

这将输出文件in reverse order 并且 grep 将在第一次匹配后停止。它还将同时搜索两个搜索词,如果它与第一个词不匹配,您就不必 grep 两次。

【讨论】:

  • 不要以为2会更快,再看OP的代码。相同的tail -n 10 被使用了两次。
【解决方案2】:

为什么不这样:

if tail -f "$jobfile.out" \ 
    | grep -F -e "Command exited with non-zero status" -e "Error termination via Lnk1e"
then
   output "$(grep $jobID $curJobsFile)"
   sed -i "/$jobID/d" "$jobIDsWithServer"
fi

这样,您可以实时搜索尾部的输出,直到找到您要查找的内容。

在不使用正则表达式时,在 grep 中使用 -F 标志会更快。

【讨论】:

  • 不知道-F 标志!
猜你喜欢
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-30
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
相关资源
最近更新 更多