3

我想从可能的巨大日志文件(> 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

但这会扫描带有所有不感兴趣的行的整个文件。有命令尾巴,但我可以给他我不知道的最后几行 - 我只知道时间戳。当第一个时间戳不匹配时,有没有办法从后面“唤醒”并停止处理?

4

4 回答 4

4

tac 是你的朋友:

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

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

于 2011-04-30T19:17:26.317 回答
1

如果我理解正确,您只需要从时间戳正则表达式获取 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
于 2011-04-29T13:49:15.627 回答
1

使用标准的 Unix 命令,除了扫描整个文件之外,您无能为力。如果您编写自己的程序,则可以对文件进行二进制搜索:

  • 寻找文件中的一个点,
  • 向前读到下一个记录开始处,
  • 检查时间戳是否太大或太小,
  • 并迭代直到在文件中找到正确的点。

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

确实,除非您要经常这样做并且可以证明性能是一个问题,否则我会选择简单的awk解决方案。

于 2011-04-29T14:04:03.453 回答
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
于 2011-04-29T08:07:29.030 回答