合并同一个键的值

有可能使用awk将同一个键的值放入一行吗? 例如

 a,100 b,200 a,131 a,102 b,203 b,301 

我可以将它们转换为像这样的文件:

 a,100,131,102 b,200,203,301 

你可以像这样使用awk:

 awk -F, '{a[$1] = a[$1] FS $2} END{for (i in a) print ia[i]}' file a,100,131,102 b,200,203,301 

我们使用-F,使用逗号作为分隔符,并使用数组a来保持聚合值。

参考: 有效的AWK编程

如果Perl是一个选项,

 perl -F, -lane '$a{$F[0]} = "$a{$F[0]},$F[1]"; END{for $k (sort keys %a){print "$k$a{$k}"}}' file 

这些命令行选项被使用:

  • -n循环输入文件的每一行
  • -l在处理之前删除换行符,然后将其添加回来
  • -a自动分割模式 – 将输入行分割成@F数组。 默认分割为空格。
  • -e执行Perl代码
  • -F autosplit修饰符,在这种情况下分裂,

@F是每行中的单词数组,以$F[0]开始索引,
$F[0]@F的第一个元素(键)
$F[1]@F的第二个元素(值)
%a是一个存储包含每个键的所有匹配的字符串的散列

TL;博士

如果您预先输入,可以使用sed来加入这些行,例如:

 sort foo | sed -nE ':a; $p; N; s/^([^,]+)([^\n]+)\n\1/\1\2/; ta; P; s/.+\n//; ba' 

多一点解释

上面的一行可以保存成一个脚本文件。 见下面的评论版本。

parse.sed

 # A goto label :a # Always print when on the last line $p # Read one more line into pattern space and join the # two lines if the key fields are identical N s/^([^,]+)([^\n]+)\n\1/\1\2/ # Jump to label 'a' and redo the above commands if the # substitution command was successful ta # Assuming sorted input, we have now collected all the # fields for this key, print it and move on to the next # key P s/.+\n// ba 

这里的逻辑如下:

  1. 假设排序的输入。
  2. 看连续两行。 如果他们的关键字段匹配,从第二行删除键并将值附加到第一行。
  3. 重复2.直到密钥匹配失败。
  4. 打印收集的值并重置以收集下一个键的值。

像这样运行它:

 sort foo | sed -nEf parse.sed 

输出:

 a,100,102,131 b,200,203,301