【问题标题】:awk counting number of digits within a given rangeawk 计算给定范围内的位数
【发布时间】:2016-07-15 20:09:19
【问题描述】:

如何计算字段中给定数字范围内的数字出现的次数?

例如,原始文本foo.txt如下所示:

2,3,4,2,4
2,3,4,32,4
2,3,4,12,4
2,3,4,4,4
2,3,4,,4
2,3,4,15,4
2,3,4,15,4

我想计算字段 #4 中的数字落在以下范围内的次数:[0,10) 和 [10,20),其中下限包括在内,上限不包括在内。

结果应该是:

范围 0-10: 2 范围 10-20:3

下面是我的 awk 代码,但我在两个范围内都得到 8600001, awk -f prog.awk foo.txt:

#!/usr/range/awk
# prog.awk

BEGIN {
    FS=",";
    $range1=0;
    $range2=0;
}
$4 ~ /[0-9]/ && $4 >= 0 && $4 < 10 { $range1 += 1 };
$4 ~ /[0-9]/ && $4 >= 10 && $4 < 20 { $range2 += 1 };
END {
    print $range1, "\t", $range2;
}

【问题讨论】:

  • 您是指“数字”还是“数字”?数字是单个数字;当然,它们也是数字,但10 是由两位数字表示的单个数字。从第 4 列的预期输出来看,您计算的是数字,而不是数字。有趣的案例是空字段;很容易将其算作零而不是一个没有数字的空字段。
  • 请注意awk 使用$ 表示字段编号,而不是一般变量。在初始化时,$range1 = 0$0 设置为0,因为range1 没有定义,所以相当于零作为数字或空字符串。删除$

标签: awk


【解决方案1】:

另一个awk

$ awk -F, '$4>=0{a[int($4/10)]++} 
             END{print "range 0-10:" a[0],"range 10-20:" a[1]}' file

range 0-10:2 range 10-20:3

可以轻松扩展以覆盖整个范围

$ awk -F, '$4>=0{a[int($4/10)]++} 
             END{for(k in a) print "range ["k*10"-"(k+1)*10"):", a[k]}' file

range [0-10): 2
range [10-20): 3
range [30-40): 1

【讨论】:

    【解决方案2】:
    $ awk -F, '0<=$4 && $4<10{a++} 10<=$4 && $4<20{b++}  END{printf "range 0-10: %i range 10-20: %i\n",a,b}' foo.txt
    range 0-10: 2 range 10-20: 3
    

    工作原理

    • 0&lt;=$4 &amp;&amp; $4&lt;10{a++}

      每次第四个字段在 [0,10) 中时都会计数。

    • 10&lt;=$4 &amp;&amp; $4&lt;20{b++}

      每次第四个字段在 [10,20) 中时都会计数。

    • END{printf "range 0-10: %i range 10-20: %i\n",a,b}

      在我们读完文件后,这会以所需的格式打印出结果。

    多行版本

    对于那些喜欢多行代码的人:

    awk -F, '
        0<=$4 && $4<10 {
            a++
        } 
    
        10<=$4 && $4<20{
            b++
        }
    
        END{
            printf "range 0-10: %i range 10-20: %i\n", a, b
        }
        ' foo.txt
    

    原代码的修改版

    在awk中,$range1是编号为range1的字段的值。这不是你想要的。如果您没有引用字段编号,请不要使用$。因此:

    BEGIN {
        FS=",";
        range1=0;
        range2=0;
    }
    $4 ~ /[0-9]/ && $4 >= 0 && $4 < 10 { range1 += 1 };
    $4 ~ /[0-9]/ && $4 >= 10 && $4 < 20 { range2 += 1 };
    END {
        print range1, "\t", range2;
    }
    

    请注意,不必将范围变量初始化为零:零是数值变量的默认值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-22
      • 2020-05-05
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 2010-09-19
      相关资源
      最近更新 更多