Linux 下遍历大文件每一行的最佳方法,最好是命令

2015-12-05 10:46:00 +08:00
 vus520
via: http://liuzhiqiangruc.iteye.com/blog/1454797

原始需求是想监控文件增加的每一行,传给外部程序处理。

实际上的办法是定时遍历文件的每行,再传给外部程序处理。
5321 次点击
所在节点    问与答
94 条回复
xufang
2015-12-05 11:39:05 +08:00
@skydiver 呃,你如果转进到 Unix 哲学,我只能推测你估计没有像我和楼主一样真实处理过大文件的文本。。。
Andiry
2015-12-05 11:48:38 +08:00
500w+行,每行算 100bytes ,也就是 500MB ,也不算什么大文件,全部读进内存,然后开多线程用 seek 分段处理就完了
skydiver
2015-12-05 11:49:01 +08:00
@xufang 这只是你的不合理推测。
逐行处理不需要把文件全读到内存里,所以跟文件大小没有关系。
vus520
2015-12-05 11:49:16 +08:00
@xufang @skydiver 二位这么执着我真是又醉又感动

现在的需求其实是找出每一行数据,交给其它进程数据,现在只是想知道,哪种方式最快最方便最省内存

我依次测试过 cat 再 loop ,试过 awk ,现在的场景是处理 50G 以上的日志文件分析进行抽取。

考虑到生产环境中并没有安装 go ,所以命令是优先的,方便集群中部署。

我正在测试几个命令的效率,回头跟大家 update 下
vus520
2015-12-05 11:51:04 +08:00
@skydiver 是的,我的需求跟你说的是一致的。不管文件多大,我每次只处理一行,直接扔给外部程序处理,这里只关注遍历文件的速度,外部程序处理的速度暂时不关注
xufang
2015-12-05 11:54:06 +08:00
@Andiry golang 欢迎您。[微笑]
xufang
2015-12-05 11:58:35 +08:00
@skydiver 。。。 这,好吧,您继续坚持 tail 遍历文件吧。,我是说服不了啦。
xufang
2015-12-05 12:07:42 +08:00
@Andiry 补上 https://blog.klauspost.com/an-async-read-ahead-package-for-go/

这套东东比手动撸 c++/java 舒服多了。至于脚本语言,有了 GIL 就别想啦。
clino
2015-12-05 12:16:54 +08:00
@vus520 tail 可以从头开始遍历啊 -n 够大就可以从头开始
xufang
2015-12-05 12:18:25 +08:00
@clino 亲,也请再看下楼主原帖哦,楼主要的是一个高效的遍历文件每一行并且做正则替换的方法。。。
ryd994
2015-12-05 12:26:17 +08:00
问题是为什么不用 tail -f 解决原始需求而是用这种绕路的方法解决一个人为的需求?

对于新需求, BC 和 EF 之间是否有顺序关系, BC 是否一定在 EF 之前, EF 是否只出现一次?如果是: sed

还有,如果你有多核的话,可以直接 seek 到 1/n 大小处,找到最近的换行,然后就可以并行化了。注意处理好边界问题。

你现在的方法估计还有个瓶颈在 IO 上,因为修改的部分不大,但要复制一份的 IO 不小。直接写个 C 程序处理并不复杂,直接在当前位置写入,表面上看是随机写,但有缓存的情况下不需要担心。
xufang
2015-12-05 12:28:53 +08:00
@ryd994 楼主这需求其实是离线收集日志,估计还用上了 fabric ansible 这些工具。所以才会这样,你琢磨一下。
ryd994
2015-12-05 12:32:06 +08:00
@xufang 那写个 C 的小程序是值得的, 反正只用到基本的文件读写方面的知识,写个真不难
xufang
2015-12-05 12:33:39 +08:00
嗯,不过我现在成了 go 粉了,在不遗余力地游说楼主呢。
ryd994
2015-12-05 12:33:48 +08:00
这个任务,瓶颈是 IO ,有条件的话上 SSD 或者全部放内存
ryd994
2015-12-05 12:35:41 +08:00
@xufang 文件读写这件事由硬件制约,并不是太适合高度并行化,用 Go 未必合适。
clino
2015-12-05 13:15:20 +08:00
@xufang 这有什么问题吗? 如果要做正则替换就做啊.
xufang
2015-12-05 13:16:22 +08:00
@ryd994 楼主还要正则替换呢
具体请看我 28 楼回复的文章,很详细了。
xufang
2015-12-05 13:17:31 +08:00
@clino 楼主要的高效哦,在他的原帖拒绝了管道的方案。
clino
2015-12-05 13:27:59 +08:00
@xufang 要的是高效 管道不一定会低效 原帖低效的原因是每一行都重新调用一个新进程,如果用同样一个进程效率不会这么低

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/241308

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX