如何计算AWK中满足数字条件的行数?

时间:2019-05-05 11:28:17

标签: awk

我有一个2列文本文件,该文件按第2列(数字,升序)排序,我试图通过计算落入设置区域内的行数来进行总结。设置为1000。本质上将读取文本文件,如果第2列中的数字介于0和1000之间,则在输出文件中将有一个新行对此进行计数,然后是输出文件的第二行我将拥有1000-2000区域,依此类推,直到读取文件末尾。

不幸的是,我已经传递的代码错过了第一行输出0-1000,并且没有正确输出数学运算……我认为它忽略了INPUT文件的第一行吗?我不知道更改有多么容易,或者是否有更优雅的书写方式...

据我了解,AWK命令说

  1. 让x = 0和y = 1000
  2. 如果$ 2> = 0 && $ 2
  3. 到达y时打印
  4. 重复y + 1000

但是我的第一个区域1000不见了

输入文件:已排序并以制表符分隔

aaaaa 675 
aaaaa 678
aaaaa 989
aaaaa 1001
aaaaa 1500
aaaaa 2020 
...
awk -F'\t' 'BEGIN{x=0;y=1000;}{
   if ($2 >= 0 && $2 < y) {x=x+1;}
   else {OFS="\t"; $2=y; $3=y+1000; $4=x; print$1,$2,$3,$4; x=0; y=y+1000}
   }' INput.txt > OUTput.txt

所以,我期待着:

aaaaa    0 1000 3
aaaaa 1000 2000 2
aaaaa 2000 3000 1
...

但是我得到的是

aaaaa 1000 2000 3
aaaaa 2000 3000 1
aaaaa 3000 4000 0 
...

给定输入文件,这是不正确的。

(...表示文件的其余部分)

3 个答案:

答案 0 :(得分:3)

除了@JamesBrown's answer,这是一个有效的版本:

awk '
BEGIN {
  FS=OFS="\t"
}
{ 
  while(c<$2) {
    if(c)
      print $1,c-1000,c,n
    n=0 
    c+=1000
  }
  n++
}
END {
  print $1,c-1000,c,n
}' file

给出示例输出:

aaaaa   0       1000    3
aaaaa   1000    2000    2
aaaaa   2000    3000    1

答案 1 :(得分:1)

让我们添加一些调试信息,请参见:

$ cat foo.awk
BEGIN {
    OFS="\t"                                                   # moved
    x=0
    y=1000
}
{
    printf "DEBUG NR=%d $2=%d y=%d\n",NR,$2,y > "/dev/stderr"  # added
    if ($2 >= 0 && $2 < y)
        x=x+1
    else {
        $2=y
        $3=y+1000
        $4=x
        print$1,$2,$3,$4
        x=0
        y=y+1000
    }
}

运行它:

$ awk -f foo.awk file
DEBUG NR=1 $2=675 y=1000
DEBUG NR=2 $2=678 y=1000
DEBUG NR=3 $2=989 y=1000
DEBUG NR=4 $2=1001 y=1000
aaaaa   1000    2000    3
DEBUG NR=5 $2=1500 y=2000  # if (1500 >= 0 && 1500 < 2000) {x=x+1} ie no print
DEBUG NR=6 $2=2020 y=2000
aaaaa   2000    3000    1

答案 2 :(得分:0)

在大多数情况下,您可以在awk中将if语句转换为模式,从而使脚本更易于理解,同时更加简洁。我对这个问题的解决方法是在名为 count.awk

的脚本中
BEGIN {
    threshold = 1000
    FS = OFS = "\t"
}

$2 > threshold {
    print first, threshold - 1000, threshold, count
    threshold += 1000
    count = 0
}

{
    first = $1
    count++
}

END {
    print first, threshold - 1000, threshold, count
}

注释

  • BEGIN模式很简单:在这里我声明阈值和定界符
  • 对于第二步中值超过阈值(模式:$2 > threshold)的那些行,我打印出到目前为止的前几行的计数,调整阈值,然后重置计数
  • 对于每一行,我保存第一列的值,然后计数。重要的是,将此块放置在$2 > threshold块的之后,否则计数将减少一个
  • 最后,我还打印了最后一批的计数

调用脚本

awk -f count.awk INput.txt > OUTput.txt