我有一个文件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
如果数据尚未排序,请使用datamash
with--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