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 往前的行数.
5. 所以可以看第三种方法和第四种就差了 X 到 Y 之间内容, 而这里面内容很少, 所以可以忽略不计. 而我猜测 head
和 tail
应该是有比较很好的优化, 所以相比 sed
就快了一些. 如果 X 到 Y 内容很大, 我猜测可能 sed
会快一点.