【问题标题】:Grouping with condition AWK使用条件 AWK 分组
【发布时间】:2014-05-27 12:12:12
【问题描述】:

您好,我有这个文本文件:

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

【问题讨论】:

  • 除非您的输入文件有更多内容,否则这些数字似乎是列/字段 $2 而不是 $3,就像您在 awk 脚本中那样。您还应该更具体地说明您的尝试到底是什么不起作用(以及您获得的输出而不是您想要获得的输出)。

标签: bash sorting loops awk


【解决方案1】:

这可以是一种方式:

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&gt;=d?d:min) 更新最小值。
  • max=(max&gt;d?max:d)} 更新最大值。
  • END{for (i=min; i&lt;=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

【讨论】:

  • int()的定义不是“给你数的整数部分”吗?为什么是数学?是否需要设置最小值?第一次使用时它会被假定为零,不是吗?
  • 哦,是的,你是对的。我正在玩整数除法并且无法获得整数部分,然后我发现了int(),但不知何故我保留了数学。关于最小值,这就是问题所在:默认为0,它永远不会被存储,因为其他字段的值大于30。这就是为什么我将第一个值存储为 min 然后继续比较。
  • 啊,对了,我没有考虑 min 的意义。对不起。
  • 不错!虽然(a[i]?a[i]:0) 可以写成a[i]+0
  • 好的,@jaypal,我将其添加到我的答案中。非常感谢!!
【解决方案2】:

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);
'

【讨论】:

  • 对于那些想知道什么是}{的人(包括我自己),它被称为Eskimo greeting
  • 很好的解决方案@choroba。虽然它不打印带有0 元素的范围。例如。 32 - 33 0 主要是因为我们的哈希中不存在密钥。我有一个ugly fix。不过想看看你的方法!
  • @choroba 感谢您的编辑。这确实是一种更好的方法。通过执行您在print "$_ - ", $_ + 1, "\t", $h{$_}+0 for $a[0] .. $a[-1] 所做的操作,我能够使丑陋的修复变得不那么丑陋,但我并不高兴,因为我必须创建一个单独的数组才能获得最小最大值。希望利用密钥进行迭代,但从未绕过它。
【解决方案3】:

我的解决方案:

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}'

【讨论】:

    猜你喜欢
    • 2019-07-09
    • 1970-01-01
    • 2017-07-03
    • 2015-04-20
    • 2014-02-01
    • 2015-01-18
    • 2020-07-26
    • 2019-02-20
    • 1970-01-01
    相关资源
    最近更新 更多