使用条件AWK进行分组

时间:2014-05-27 12:12:13

标签: bash sorting loops awk

您好我有这个文本文件:

chr1      30.3
chrx      30.5
chr3      31.3
chr4      31.7
chrX      33.6
chr1      34.1

我想得到:

30 - 31    2
31 - 32    2
32 - 33    0
33 - 34    1
34 - 35    1

我正在尝试使用这个bash和awk代码,但它不起作用。你能帮帮我吗?

#!/bin/bash

for i in {30..60..1}
do
    h=$i

    let "h += 1"

    export i
    export h 

    awk -v g=$i -v c=$h '{if ($3 >= $g && $3< $c) print $0}' /home/filip/Desktop/AMrtin\ Hynek/doktor.txt | awk   'END{print $i"-"$h,"\t",NR}'

done

3 个答案:

答案 0 :(得分:5)

这可以是一种方式:

awk '{d=int($2)
      a[d]++
      if (NR==1) {min=d}
      min=(min>=d?d:min)
      max=(max>d?max:d)}
      END{for (i=min; i<=max; i++) print i, "-", i+1, a[i]+0}' file

解释

跟踪数组a[]中的外观,然后在minmax之间循环索引。

  • d=int($2)获取数字的整数部分。
  • a[d]++增加数组上此字段的出现次数。
  • if (NR==1) {min=d}在第一行设置最小值。
  • min=(min>=d?d:min)更新最低要求。
  • max=(max>d?max:d)}更新最大值。
  • END{for (i=min; i<=max; i++) print i, "-", i+1, a[i]+0}遍历打印外观的索引。如果未找到任何值,则根据+0技巧(thanks Jaypal!)打印0。

测试

$ awk '{d=int($2); a[d]++; if (NR==1) {min=d}; min=(min>=d?d:min); max=(max>d?max:d)} END{for (i=min; i<=max; i++) print i, "-", i+1, a[i]+0}' file
30 - 31 2
31 - 32 2
32 - 33 0
33 - 34 1
34 - 35 1

答案 1 :(得分:4)

Perl解决方案:

perl -ane '
        $h{ int $F[1] }++
    }{
        print "$_ - ", $_ + 1, "\t", $h{$_}, "\n"
            for sort { $a <=> $b } keys %h
'

要获得零线,您可以从List::Util添加minmax

perl -MList::Util=min,max -ane '
        $h{ int $F[1] }++
    }{
        print "$_ - ", $_ + 1, "\t", 0 + $h{$_}, "\n"
            for min(keys %h) .. max(keys %h);
'

答案 2 :(得分:1)

我的解决方案:

awk '{print $2}' file.txt | sed 's/\..*//' | sort | uniq -c | awk '{print $2, $1}'  > counts.txt
paste <(seq 30 34) <(seq 31 35) | join -a1 - counts.txt  | awk '!$3{$3=0}{print $1 "-" $2 " " $3}'