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 -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,1
和 121,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
大家好,我得到了这个虚拟数据:
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 -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,1
和 121,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