【问题标题】:Reading groups of lines from a large text file从大文本文件中读取行组
【发布时间】:2017-01-03 20:19:21
【问题描述】:

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

通过浏览 Stack Overflow,我发现 bash 命令:

tail -n+NUMstart file |head -nNUMend

是获取从 NUMstart 到 NUMend 的单行或一组行的最快方法。但是,当读取多组行时,这似乎效率低下。通常,该技术不会那么重要,但是对于这么大的文件,它会产生巨大的影响。

有没有比对每组行使用上述命令更好的方法?我假设答案很可能是一个 bash 命令,但我真的对任何能做得最好的语言/工具持开放态度。

【问题讨论】:

    标签: bash file text


    【解决方案1】:

    使用 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
    

    【讨论】:

    • 我很好奇这是否会比awk 快​​得多。
    • 这将扫描整个文件,不能比awk快,最后一行后退出。
    【解决方案2】:

    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
    

    在最后打印的行之后提供提前退出。无错误检查,范围应按递增顺序提供。

    【讨论】:

    • 好方法。但是,我不认为范围馈送在这里是一个特别的问题,所以 BEGIN 块在某种程度上是无关紧要的(对我来说)。
    【解决方案3】:

    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
    

    【讨论】:

      猜你喜欢
      • 2015-11-26
      • 2017-01-21
      • 1970-01-01
      • 2013-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多