Grep以相反顺序而不读取整个文件

Ama*_*way 6 grep reverse posix large-files

我有一个可能非常大(10+ GB)的日志文件.我想找到表达式的最后一次出现.是否可以使用标准posix命令执行此操作?

以下是一些不太适合的类似问题的潜在答案.

  • 使用tail -n <x> <file> | grep -m 1 <expression>:我不知道表达式有多远,所以我不知道<x>会是什么.它可能是之前的几GB,所以你要拖尾整个文件.我想你可以循环并递增<x>直到找到它,但是你会反复阅读文件的最后一部分.
  • 使用tac <file> | grep -m 1 <expression>:tac读取整个源文件.一旦发现某些输出,就有可能将某些东西连接到sigkill tac上?这会有效吗?
  • 使用awk/sed:我很确定这些都始终从文件的顶部开始(虽然我可能错了,但我的sed-fu并不强大).
  • "没有加速,所以为什么要打扰":我认为这是不正确的,因为文件系统可以在不读取整个文件的情况下寻找文件的末尾.有一些试验和错误/缓冲来查找每个新行,但与读取(例如)从未使用的10 GB相比,这不应该减慢很多.
  • 编写一个python/perl脚本来执行此操作:如果没有人可以提出更好的建议,这是我的后退.我宁愿坚持可以直接通过命令行完成的事情,因为我直接通过ssh执行它,而且我也不必上传脚本文件.在python中使用mmap的rfind(),我认为我们可以在几行中完成它,前提是find的表达式是静态的(不幸的是,我的不是).正则表达式需要更多的工作,就像这样.

如果它有帮助,表达式锚定在一行的开头,例如:"^foo \d+$".

Ed *_*ton 4

无论您编写什么脚本,几乎肯定会比以下脚本慢:

tac file | grep -m 1 '^foo [0-9][0-9]*$'
Run Code Online (Sandbox Code Playgroud)

  • 好吧,看起来当 grep 完成时,管道被破坏,内核向 tac 发送 SIGPIPE,tac 的响应是关闭输入文件,然后以代码 1 退出。这就是它不读取整个文件的原因。因此,看起来这个解决方案是最简单、最快的,并且不会读取整个文件(正如我担心的那样)。 (3认同)