我尝试过的

我尝试过的

我有一个文件user-history.txt,文件内容采用以下模式。

user-1 6
user-1 7
user-2 6
user-2 7
user-2 8
user-3 6
user-3 7
user-3 9
user-4 6

我想合并记录,以便每个用户仅被提及一次,并分别合并第二列。

所需输出

user-1 6,7
user-2 6,7,8
user-3 6,7,9
user-4 6

我尝试过的

由于我还没有足够的经验,所以我无法解决这个问题。我一直在寻找其他解决方案,尽管存在类似的问题,但我还没有找到任何可以解决我的特定问题的解决方案。

如果 (G)AWK 不是用于此任务的最简单工具,我愿意接受其他解决方案。

详细的解释将不胜感激,这样我就可以提高我的知识。

答案1

$ datamash -W groupby 1 collapse 2 <user-history.txt
user-1  6,7
user-2  6,7,8
user-3  6,7,9
user-4  6

这使用 GNUdatamash折叠第二列 ( ) 的条目并将它们分组到第一列 ( , 或)collapse 2中的键,将连续的空白字符视为字段分隔符 ( , 或)。groupby 1-g 1-W--whitespace

如果数据尚未排序,请使用datamashwith--sort-s,如果数据中有要忽略的重复键值对,请使用unique 2代替collapse 2

答案2

$ cat tst.awk
$1 != prev {
    if ( prev != "" ) {
        print prev, vals
    }
    prev = $1
    vals = $2
    next
}
{ vals = vals "," $2 }
END {
    print prev, vals
}

$ awk -f tst.awk file
user-1 6,7
user-2 6,7,8
user-3 6,7,9
user-4 6

我认为它的作用是显而易见的,不需要任何解释,但如果有任何部分您不明白,请在下面的评论中提问。

答案3

这是一种方法:

{
  if ($1 in users) users[$1] = users[$1] "," $2
  else users[$1] = $2
}

END { for (user in users) { print user, users[user] } }

这会查看每一行,并检查用户是否已经被看到(由数组确定users)。如果是,则将第二条记录添加到存储的信息中,并用逗号分隔;否则,使用第二记录来初始化所存储的信息。

一旦处理完所有输入,users就会迭代该数组,并提取并打印存储的信息。

请注意,不会保留用户的顺序。由于您使用的是 GAWK,因此您可以使用一个扩展解决这个问题:

END { PROCINFO["sorted_in"] = "@ind_str_asc"; for (user in users) { print user, users[user] } }

答案4

一种方法可以是

awk '
NR==1||prev!=$1{
  if (NR!=1) { print RS}
  print;prev=$1
  next
}
{ $1=",";print }
END{print RS}
' OFS= ORS= file

user-1 6,7
user-2 6,7,8
user-3 6,7,9
user-4 6

相关内容