在一个逗号分隔的列表中创建对象大小的摘要

use*_*009 0 sed awk text-processing

我有一个包含两个字段的大文件,第一个字段表示对象名称,第二个字段表示该对象的大小:

A 1
A 2
B 4
ABC 12
C 5
A 9
B 3
ABC 6
Run Code Online (Sandbox Code Playgroud)

我想用以下格式总结列表:

A 1,2,9
ABC 12,6
B 4,3
C 5
Run Code Online (Sandbox Code Playgroud)

我想出的解决方案是创建文件中存在的对象的唯一列表,遍历它并将其与原始文件匹配

for object in $(awk '{print $1}' objects_with_sizes.txt | sort -u);do
    echo -n "$object "
    awk -v pattern="$object" '$1==pattern{printf "%s%s" ,sep,$2;sep=","} END{print ""}' objects_with_sizes.txt  
done 

Run Code Online (Sandbox Code Playgroud)

此实现需要很长时间才能运行,是否有更有效的方法来创建所需的输出?

αғs*_*нιη 5

$ awk '{ object[$1]= (object[$1]==""?"":object[$1] ",") $2 }
  END  { for(obj in object) print obj, object[obj] }' infile
A 1,2,9
B 4,3
C 5
ABC 12,6
Run Code Online (Sandbox Code Playgroud)

效率更高一点(内存的使用;对于无法放入内存的大文件很重要),即不将文件部分缓冲到内存中,而 awk 命令单独执行上述操作,但仅在对象键更改之前:

$ <infile sort -k1,1 -k2,2n |\
  awk 'pre!=$1 { if(obj) { print obj; obj="" } }
               { obj= (obj==""?$1 " ":obj ",") $2; pre=$1 }
  END{ if(obj) print obj }'
A 1,2,9
ABC 6,12
B 3,4
C 5
Run Code Online (Sandbox Code Playgroud)


Fre*_*ddy 5

使用 GNU datamash

$ datamash -t ' ' -s -g 1 collapse 2 <file
A 1,2,9
ABC 12,6
B 4,3
C 5
Run Code Online (Sandbox Code Playgroud)

选项:

  • -t '_' 使用空格字符作为字段分隔符
  • -s 在分组之前对输入进行排序
  • -g 1 在第一个字段上分组
  • collapse 2 将第二个字段的值折叠为逗号分隔的列表