Linux Bash按唯一列进行计数和总结

时间:2018-09-05 11:23:46

标签: bash awk uniq

我有一个带有这样的行的文本文件(在Linux Bash中):

A B C D
A B C J
E B C P
E F G N
E F G P
A B C Q
H F S L
G Y F Q
H F S L

我需要找到前3列具有唯一值的行,打印它们的计数,然后为每个唯一行打印汇总的最后一列,所以结果是这样的:

3 A B C D,J,Q
1 E B C P
2 E F G N,P
1 G Y F Q
2 H F S L

我尝试过的事情:

cat FILE | sort -k1,3 | uniq -f3 -c | sort -k3,5nr

也许有什么建议吗?

谢谢!

4 个答案:

答案 0 :(得分:1)

最简单的方法是执行以下操作:

awk '{key=$1 OFS $2 OFS $3; a[key]=a[key]","$4; c[key]++}
     END{for(key in a) { print c[key],key,substr(a[key],2) }}' <file>

如果您不想重复,可以这样做

awk '{ key=$1 OFS $2 OFS $3; c[key]++ }
     !gsub(","$4,","$4,a[key]) {a[key]=a[key]","$4; }
     END{for(key in a) { print c[key],key,substr(a[key],2) }} <file>

答案 1 :(得分:0)

能否请您尝试以下操作,如果有帮助,请告诉我。 这将使您按照与Input_file的$1$2$3出现相同的顺序进行输出。

awk '
!a[$1,$2,$3]++{
  b[++count]=$1 FS $2 FS $3
}
{
  c[$1,$2,$3]=c[$1,$2,$3]?c[$1,$2,$3] "," $4:$0
  d[$1 FS $2 FS $3]++
}
END{
  for(i=1;i<=count;i++){
    print d[b[i]],c[b[i]]
  }
}
' SUBSEP=" "  Input_file

答案 2 :(得分:0)

另一个使用GNU awk和2d数组删除$4中的重复项:

$ awk '{
    i=$1 OFS $2 OFS $3                        # key to hash
    a[i][$4]                                  # store each $4 to separate element
    c[i]++                                    # count key references
}
END {
    for(i in a) {                             
        k=1                                   # comma counter for output
        printf "%s %s ",c[i],i                # output count and key
        for(j in a[i])                        # each a[]i[j] element
            printf "%s%s",((k++)==1?"":","),j # output commas and elements
        print ""                              # line-ending
    }
}' file

以默认的随机顺序输出:

2 E F G N,P
3 A B C Q,D,J
1 G Y F Q
1 E B C P
2 H F S L

由于我们使用的是GNU awk,因此通过设置PROCINFO["sorted_in"]="@ind_str_asc"可以很容易地影响输出的顺序:

3 A B C D,J,Q
1 E B C P
2 E F G N,P
1 G Y F Q
2 H F S L

答案 3 :(得分:0)

您可以利用GNU datamash

$ cat input
A B C D
A B C J
E B C P
E F G N
E F G P
A B C Q
H F S L
G Y F Q
H F S L
$ datamash -t' ' --sort groupby 1,2,3 unique 4 count 4 < input
A B C D,J,Q 3
E B C P 1
E F G N,P 2
G Y F Q 1
H F S L 2

不幸的是,这将计数输出为最后一列。如果绝对有必要将其作为第一列,则必须重新设置其格式:

$ datamash -t' ' --sort groupby 1,2,3 unique 4 count 4 < input | awk '{$0=$NF FS $0; NF--}1'
3 A B C D,J,Q
1 E B C P
2 E F G N,P
1 G Y F Q
2 H F S L