BASH 根据两列选择和计算非重复

BASH choosing and counting distinct based on two column

大家好,我得到了这个虚拟数据:

115,IROM,1
125,FOLCOM,1
135,SE,1
111,ATLUZ,1
121,ATLUZ,2
121,ATLUZ,2
142,ATLUZ,2
142,ATLUZ,2
144,BLIZZARC,1
166,STEAD,3
166,STEAD,3
166,STEAD,3
168,BANDOI,1
179,FOX,1
199,C4,2
199,C4,2

期望的输出:

IROM,1
FOLCOM,1
SE,1
ATLUZ,3
BLIZZARC,1
STEAD,1
BANDOI,1
FOX,1
C4,1

这来自计算不同的游戏 ID(115,125 等)。例如

111,ATLUZ,1
121,ATLUZ,2
121,ATLUZ,2
142,ATLUZ,2
142,ATLUZ,2

将会

ATLUZ,3 

因为它有 3 个不同的游戏 ID

我尝试使用

cut -d',' -f 2 game.csv|uniq -c

我在哪里得到以下输出

  1 IROM
  1 FOLCOM
  1 SE
  5 ATLUZ
  1 BLIZZARC COMP
  3 STEAD
  1 BANDOI
  1 FOX
  2 C4

我该如何解决这个问题?使用 bash ?

在执行cut命令之前,做一个uniq。这将删除多余的行,然后您按照您的命令进行操作,即应用 cut 来提取 2 字段并执行 uniq -c 来计算字符

uniq game.csv | cut -d',' -f 2 | uniq -c

能否请您也尝试单次关注awk

awk -F, '
!a[,,]++{
  b[,,]++
}
!f[]++{
  g[++count]=
}
END{
  for(i in b){
    split(i,array,",")
    c[array[2]]++
  }
  for(q=1;q<=count;q++){
    print c[g[q]],g[q]
  }
}' SUBSEP=","  Input_file

它将给出与 Input_file 的第二个字段相同的输出顺序,如下所示。

1 IROM
1 FOLCOM
1 SE
3 ATLUZ
1 BLIZZARC
1 STEAD
1 BANDOI
1 FOX
1 C4

不太优雅,但您也可以使用 awk。如果不允许相同的 ID+NAME 组合总是连续出现,则必须在输出前通过读取整个文件来计算每个组合:

awk -F, '{c[,]+=1}END{for (ck in c){split(ck,ca,SUBSEP); print ca[2];g[ca[2]]+=1}for(gk in g){print gk,g[gk]}}' game.csv

这将首先计算每个 [COL1,COL2] 对,然后对每个 COL2 计算有多少不同的 [COL1,COL2] 对是非零的。

使用GNU datamash:

datamash -t, --sort --group 2 countunique 1 < input

使用awk

awk -F, '!a[,]++{b[]++}END{for(i in b)print i FS b[i]}' input

使用sort, cut, uniq:

sort -u -t, -k2,2 -k1,1 input | cut -d, -f2 | uniq -c

测试运行:

$ cat input
111,ATLUZ,1
121,ATLUZ,1
121,ATLUZ,2
142,ATLUZ,2
115,IROM,1
142,ATLUZ,2
$ datamash -t, --sort --group 2 countunique 1 < input
ATLUZ,3    
IROM,1

如您所见,121,ATLUZ,1121,ATLUZ,2 被正确地认为只是一个 game ID

这也可以解决问题。唯一的问题是你的输出没有排序。

awk 'BEGIN{ FS = OFS = "," }{ a[ FS ] }END{ for ( i in a ){ split(i, b, "," ); c[b[1]]++ } for ( i in c ) print i, c[i] }' yourfile

输出:

BANDOI,1
C4,1
STEAD,1
BLIZZARC,1
FOLCOM,1
ATLUZ,3
SE,1
IROM,1
FOX,1