从End到Beginning唤醒文件的更快方法?

时间:2018-05-14 13:25:05

标签: bash awk tac

我希望从文件底部开始,直到开始。我尝试使用tac并将其传递到我的awk命令中,但速度非常慢(2GB文件为15秒)。与正常搜索相比(同一文件为3秒)。我还将awk命令输入tail -n +1 | head -n 50以在50个结果后停止。

tac文件有更快捷的方法吗?或者至少从下往上开始搜索?

大局是创建一个带有参数(开始日期,结束日期,搜索条件)的python脚本,并使用它们搜索日期组织的日志文件。一次返回50个结果。

如果用户想要按降序搜索(最新日期到最早日期),我需要从头到尾阅读。

升序结果的示例命令('最旧到最新): (我使用find,因为是用户指定的参数,它可能会引用所有文件(* .txt))

  • 开始日期:2018-03-04T03:45
  • 结束日期:2018-03-05T16:24
  • 搜索字词:马铃薯

find '/home/logs/' -type f -name 'log_file.txt' -exec cat {} \+ 2>&1| LANC=C fgrep 'Potato' | LC_ALL=C IGNORECASE=1 awk -v start="2018-03-04T03:45:00" -v stop="2018-03-05T16:24:59" 'BEGIN{IGNORECASE=1;} {line=$0; xz=" "; for(i=4;i<=NF;i++){xz=xz" "$i};} ($1>=start&&$1<=stop) && (tolower(xz) ~ /Potato/) {print line}' | tail -n +1 | head -n 50

tail -n +1 | head -n 50将返回前50场比赛。

此命令大约需要3-4秒才能找到结果,但是如果我在tac中,则需要接近20秒。

3 个答案:

答案 0 :(得分:2)

一切都取决于您所拥有的awk代码,但我想到的一些解决方案是:

  • 如果您打印每一行:

    tac <file> | awk '(NR > 50){exit}{do-your-stuff}'
    
  • 如果仅使用awk

    打印几行
    tac <file> | awk '(c > 50){exit} 
                      { do-part-of stuff;
                        print foobar; c++;
                        do-remaining part}'
    

两个解决方案在前50行打印后终止awk。这样您就不必处理完整的2GB文件。 50条打印线后的终止模仿了tail -n +1 | head -n 50

答案 1 :(得分:1)

好吧,如果你有内存,请在END部分哈希记录并向后处理:

$ for i in {a..e} ; do echo $i ; done |   
  awk '{ a[NR]=$0 }       # hash to a, NR as key
  END {                   # in the end
      for(i=NR;i>=1;i--)  # process a in descending order
          c++             # process
      print c
}'
5

更新:我在上面测试了1 GB文件(36 M记录)。它在1分钟内进行了哈希计算并吸收了大约4.5 GB的内存。

答案 2 :(得分:1)

打开文件要快得多,并在文件结束前寻找一些金额。 Perl在这里很方便:

perl -Mautodie -se '
    $size = -s $file;
    $blocksize = 64000;
    open $fh, "<", $file;
    seek $fh, $size - $blocksize, 0;
    read $fh, $data, $blocksize;
    @lines = split "\n", $data;
    # last 50 lines
    print join "\n", reverse @lines[-51..-1];
' -- -file="filename"

我们可以在那里抛出一个循环,所以在它读取最后一个块之后,它可以寻找到最后减去2个块并读取一个块等。

但是如果你想从下到上处理整个巨大的文件,你将不得不期待它需要时间。