从后面直到时间戳awk一个巨大的日志文件

时间:2011-04-29 07:58:48

标签: bash unix text logfiles

我希望从可能的大型日志文件(> 50..1000mb)中获取给定时间戳“t0”以来的最后一部分:

     __________________
    |1 xxx xxx ...     |
    |2 xxx ...         |     uninteresting part
    |4 ...             |
    |...               |
 ___|423 ...           | ___ timestamp t0
    |425 xxx ...       |
    |437 ...           |
    |...               |     <-- i want this part ( from t0 to EOF)
    |__________________|

另外一个约束是我想用简单的bash命令来做这件事。一个简单的解决方案可能是:

awk '$1 > 423' file.log

但是这会用所有不感兴趣的行扫描整个文件。这是命令 tail ,但我可以给他他想要的最后一行我不知道的数量 - 我只知道时间戳。有没有办法从后面“晃动”并在第一个时间戳不匹配时停止处理?

4 个答案:

答案 0 :(得分:4)

tac是你的朋友:

tac file.log | awk '{ if ($1 >= 423) print; else exit; }' | tac

tac将从最后一行开始转储文件的每一行,然后转到文件的开头。做一次得到你想要的线,然后再做一次来修理他们的订单。

答案 1 :(得分:1)

如果我理解正确,你只需要从时间戳regexp到文件末尾的n行。

请不要说你的大文件是这样的:

~$ cat > file << EOF
rubish
n lines of rubish
more rubish
timestamp regexp
interesting
n interesting lines
interesting
end of file
EOF

如果您能够获得正在寻找的时间戳的可行正则表达式,您可以使用sed获得所需的部分:

~$ sed -n '/timestamp regexp/,$ {p}' file
timestamp regexp
interesting
n interesting lines
interesting
end of file

答案 2 :(得分:1)

使用标准的Unix命令,除了扫描整个文件之外,没有什么可以做的。如果你编写自己的程序,你可以对文件进行二进制搜索:

  • 寻找文件中的一个点,
  • 阅读转发到下一个记录开始,
  • 检查时间戳是太大还是太小,
  • 并迭代,直到找到文件中的正确位置。

如果时间戳是纯数字,您甚至可以使用线性插值而不是纯二进制搜索进行搜索;如果邮票更复杂,它可能不值得额外编码,但这取决于你需要多长时间。

事实上,除非你要做很多事情并且可以证明性能是一个问题,否则我会选择简单的awk解决方案。

答案 3 :(得分:0)

你可以轮询,直到你点击“423”。只是一个假设的例子(未经测试)

n=100 # number of lines you want to go back
while true
do
  if tail -$n file | grep -q "423" ;then
     tail -$n file | awk '$1>423'
     break
  else
     ((n+=100)) # increment every 100 lines
  fi
done