从一个大文件中打印每一行,其中前N行满足特定条件

3

我希望能够打印大文件中前10行特定列(在下面的示例中,第9列的值小于1)具有特定值的每一行。我不想将整个文件存储在内存中。我尝试使用awk来实现这个目的,如下所示:

awk 'BEGIN{FS=","}
   {
   for (i=FNR,i<FNR+10, i++) saved[++s] = $0 ; next
   for (i=1,i<s, i++)
       if ($9<1)
   print saved[s]; delete saved; s=0
  }' file.csv

这个命令的目标是保存前10行,然后检查这些行中第9列是否符合我的条件,最后打印当前行。如果有任何帮助或更有效的建议,请不吝赐教!

请使用带有分号的 for( .. ; .. ; .. ),而不是逗号。 - Lars Fischer
2个回答

2

无需在内存中存储任何内容或对值进行任何显式循环。如果最后10行(包括当前行)的$9值小于1,则只需打印当前行:

awk -F, '(c=($9<1?c+1:0))>9' file

当然,由于您没有提供任何样本输入或期望输出,因此未经测试,请检查数学公式,但这是正确的方法,如果数学有误,则调整修复的方法只需将>9更改为>10或您需要的任何其他数字。


1
这是GNU Awk的解决方案:

chk_prev_lines.awk

BEGIN { FS=","
        CMP_LINE_NR=10
        CMP_VAL = 1     }

FNR > CMP_LINE_NR {
        ok = 1
        # check the stored values
        for( i = 0; i< CMP_LINE_NR; i++ ) {
          if ( !(prev_Field9[ i ] < CMP_VAL) ) {
             ok = 0
             break # early return
          }
        }
        if( ok ) print
      }

      { # store $9 for the comparison
        prev_Field9[ FNR % CMP_LINE_NR] = $9
      }

使用方法如下:awk -f chk_prev_lines.awk your_file

解释

  • CMP_LINE_NR 确定从前几行存储的值的数量
  • CMP_VAL 确定用于比较的值
  • 条件 FNR > CMP_LINE_NR 确保被检查前几行的第一行是具有 CMP_LINE_NR +1 的行。它是第一个具有这么多前面行的行。
  • 最后一个操作存储值 $9。这个操作对所有行执行。

在awk中不要使用全大写的变量名,因为这会使它们看起来像内置变量名,并可能与内置变量名发生冲突。此外,这可能只是一种风格问题,但通常变量的命名方式是通过下划线分隔单词 prev_field9 或者通过更改大小写 prevField9,但是像 prev_Field9 这样同时使用两种方式看起来很奇怪,我认为如果以后需要增强代码,人们很难记住如何使用这种方式,这对于awk来说是一个特别的问题,因为你不需要初始化变量,所以拼写错误只会创建一个新变量。 - Ed Morton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接