Skip to content

Linux 输出大文件的一小段

复制本地路径 | 在线编辑

一个大文件输出其中的小部分行,在网上找到了解决方案, 发现有好几种, 记录一下自己的看法。重点在后面的理解

参考: https://unix.stackexchange.com/questions/47407/cat-line-x-to-line-y-on-a-huge-file

解决方案

假如输出 X 到 Y 行, 有这几种方式

awk "NR >= X && NR <= Y" /path/to/file
tail -n "+$X" /path/to/file | head -n "$((Y-X+1))"
head -n "+$Y" /path/to/file | tail -n "$((X))"
sed -n -e 'X,Y p' -e 'Y q' /tmp/a

思考

上面的网站说第二种是最快的,这个让我感到很困惑,第二或者三种方法按理来说 tail 前的所有内容都会传入到 head 中,应该很浪费时间, 而第四种方法中利用了 sed 的指定特定行的特点,不应该很快吗。

解释如下:

  1. 找到文件的某一行没有专门的方法, 只有遍历文件通过有多少 '\n' 来实现。 以前在汇编和 C 语言中有文件指针偏移,但是那个是偏移字节数,偏移行数确实是无法立刻完成的。所以即使使用 sed 中的指定行其实也是需要遍历的。

  2. 第二种方法中 tail 会从后往前扫,除了前 X 行不会扫到;然后 head 从前往后扫,会扫 (Y-X) 行。假如文件一共 N 行, 那么扫过的内容为 (N-X) + (Y-X), 也就是从 X 往后的行数 加上 X 到 Y 的行数。

  3. 第三种方法一共是 (Y) + (Y-X), 也就是从 Y 往前的行数 加上 X 到 Y 行数

  4. 第四种方法中 sed 就会一直往后扫, 内容是从 Y 往前的行数。

对比一下,如果 X 比较靠后了,那么第二种方法会比第四种方法要更快。如果 Y 比较靠前,那么第四种 sed 应该更快。

Comments

本文阅读 Loading 本站访问 Loading 访客 Loading