从大文本文件中读取行组

时间:2017-01-03 20:19:22

标签: bash file text

我希望从大型(~870,000,000行)文本文件中提取某些行。例如,在50行文件中,我可能需要3-6,18-27和39-45行。

从浏览Stack Overflow,我发现了bash命令:

tail -n+NUMstart file |head -nNUMend

是获得从NUMstart开始并转到NUMend的单行或一组行的最快方法。但是,当读取多组线时,这似乎效率低下。通常情况下,这种技术并不重要,但是对于文件这么大,它会产生很大的不同。

除了对每组线使用上述命令之外,还有更好的方法吗?我假设答案很可能是一个bash命令,但我真的对任何能够做到最好的语言/工具开放。

3 个答案:

答案 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