我希望从大型(~870,000,000行)文本文件中提取某些行。例如,在50行文件中,我可能需要3-6,18-27和39-45行。
从浏览Stack Overflow,我发现了bash命令:
tail -n+NUMstart file |head -nNUMend
是获得从NUMstart开始并转到NUMend的单行或一组行的最快方法。但是,当读取多组线时,这似乎效率低下。通常情况下,这种技术并不重要,但是对于文件这么大,它会产生很大的不同。
除了对每组线使用上述命令之外,还有更好的方法吗?我假设答案很可能是一个bash命令,但我真的对任何能够做到最好的语言/工具开放。
答案 0 :(得分:3)
用sed:
显示第3-6,18-27和39-45行sed -n "3,6p;18,27p;39,45p" file
也可以从文件中提供sed。
文件内容foobar
:
3,6p 18,27p 39,45p
用法:
sed -n -f foobar file
答案 1 :(得分:1)
awk
救援!
awk -v lines='3-6,18-27,39-45' '
BEGIN {n=split(lines,a,",");
for(i=1;i<=n;i++)
{split(a[i],t,"-");
rs[++c]=t[1]; re[c]=t[2]}}
{for(i=s;i<=c;i++)
if(NR>=rs[i] && NR<=re[i]) {print; next}
else if(NR>re[i]) s++;
if(s>c) exit}' file
在最后一行打印后提供提前退出。没有错误检查,应按递增顺序提供范围。
答案 2 :(得分:0)
tail -n XX file | head -n YY
对于不同范围的问题是您运行了几次,因此效率低下。否则,benchmarks表明它们是最佳解决方案。
对于这种特定情况,您可能希望使用awk
:
awk '(NR>=start1 && NR<=end1) || (NR>=start2 && NR<=end2) || ...' file
在你的情况下:
awk '(NR>=3 && NR<=6) || (NR>=18 && NR<=27) || (NR>=39 && NR<=45)' file
也就是说,您对范围进行分组,让awk
在相应的行发生时打印它们,只需循环遍历文件一次。添加最终NR==endX {exit}
(endX
作为最后一个范围内的结束项目)可能也很有用,这样一旦读取了最后一个有趣的行,它就会完成处理。
在你的情况下:
awk '(NR>=3 && NR<=6) || (NR>=18 && NR<=27) || (NR>=39 && NR<=45); NR==45 {exit}' file