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
各ユーザーが一度だけ言及されるようにレコードをマージし、2番目の列を別々にマージしたいと思います。
希望の出力
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
これは、GNUを使用してdatamash
2番目の列()の項目を縮小し、それを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
1つの方法は次のとおりです。
{
if ($1 in users) users[$1] = users[$1] "," $2
else users[$1] = $2
}
END { for (user in users) { print user, users[user] } }
これは各行を見て、ユーザーが表示されていることを確認します(配列によって決まりますusers
)。その場合は、保存された情報に2番目のレコードをカンマで区切って追加し、そうでない場合は、2番目のレコードを使用して保存された情報を初期化します。
すべての入力が処理されると、users
配列が繰り返され、保存された情報が抽出され印刷されます。
ユーザーの順序は維持されません。 GAWKを使用しているので、次のものを使用できます。拡張この問題を解決してください。
END { PROCINFO["sorted_in"] = "@ind_str_asc"; for (user in users) { print user, users[user] } }
答え4
1つのアプローチは次のとおりです。
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