次のファイルがあります。
xxx ax1 bx1
xxx ax2 bx2 cx2
xxx ax3 bx3
yyy ay1 cy1
zzz az1 cz1
zzz az1 bz2
...
私は次の出力が欲しい:
xxx ax1,ax2,ax3 bx1,bx2,bx3 cx2
yyy ay1 cy1
zzz az1 bz2 cz1
...
私はawkを使ってみましたawk -F'\t' -v OFS='\t' '{x=$1;$1="";a[x]=a[x]$0}END{for(x in a)print x,a[x]}' file
。しかし、このコマンドはその列が属する列を無視し、出力は私が望むものとは異なります。
答え1
awk '
BEGIN{ FS=OFS="\t" }
{ for(i=2; i<=NF;i++)
if (!seen[$1, $i, i]++)
grp[$1, i]=(grp[$1, i]==""?"":grp[$1, i] ($i!=""?",":"")) $i
else
grp[$1, i]= grp[$1, i]
}
END{ for(x in grp) {
split(x, tmp, SUBSEP);
join[tmp[1]]=(join[tmp[1]]==""?"":join[tmp[1]] OFS) grp[x]
}
for (x in join) print x, join[x]
}' infile
出力:
yyy ay1 cy1
xxx ax1,ax2,ax3 bx1,bx2,bx3 cx2
zzz az1 bz2 cz1
フィールドが正しい位置にあることを確認するには、括弧でフィールドを囲みます。
awk '
BEGIN{ FS=OFS="\t" }
{ for(i=2; i<=NF;i++)
if (!seen[$1, $i, i]++)
grp[$1, i]=(grp[$1, i]==""?"":grp[$1, i] ($i!=""?",":"")) $i
else
grp[$1, i]= grp[$1, i]
}
END{ for(x in grp) {
split(x, tmp, SUBSEP);
join[tmp[1]]=(join[tmp[1]]==""?"":join[tmp[1]] OFS) "["grp[x]"]"
}
for (x in join) print x, join[x]
}' infile
出力:
yyy [ay1] [] [cy1]
xxx [ax1,ax2,ax3] [bx1,bx2,bx3] [cx2]
zzz [az1] [bz2] [cz1]
メモ:
- この答えは、入力がソートされているかどうかに関係なく機能します。
- この答えは出力履歴を混乱させます。
- このコードは
!seen[$1, $i, i]++
次の目的で使用されます。列の各IDエントリは一意です。。 IDに関係なく、すべての列から重複したエントリを削除するには!seen[$1, $i]++
)に変更します。
たとえば、
$ cat infile
xxx ax1 ax1
xxx ax1 bx2 ax3
xxx ax3 bx2
yyy ay1 ay1 cy3
zzz az1 bz3 cz1
zzz az1 bz2 bz3
Output(when !seen[$1, $i, i]++
);そのIDに属する各列の重複エントリのみを削除します。
yyy [ay1] [ay1] [cy3]
xxx [ax1,ax3] [ax1,bx2] [ax3]
zzz [az1] [bz3,bz2] [cz1,bz3]
出力( seen[$1, $i]++
);項目の列位置に関係なく、すべての重複項目が削除されます。
yyy [ay1] [] [cy3]
xxx [ax1] [bx2] [ax3]
zzz [az1] [bz3,bz2] [cz1]
答え2
$ cat tst.awk
BEGIN { FS=OFS="\t" }
$1 != prev {
if ( NR > 1 ) {
prt()
}
prev = $1
}
{
for ( i=1; i<=NF; i++ ) {
if ( ($i == "") || (seen[i,$i]++) ) {
uniq[i]
}
else {
uniq[i] = (uniq[i] == "" ? "" : uniq[i] ",") $i
}
}
}
END {
prt()
}
function prt( i) {
for ( i=1; i in uniq; i++ ) {
printf "%s%s", (i>1 ? OFS : ""), uniq[i]
}
print ""
delete uniq
delete seen
}
$ awk -f tst.awk file
xxx ax1,ax2,ax3 bx1,bx2,bx3 cx2
yyy ay1 cy1
zzz az1 bz2 cz1
$ awk -f tst.awk file | column -s$'\t' -t
xxx ax1,ax2,ax3 bx1,bx2,bx3 cx2
yyy ay1 cy1
zzz az1 bz2 cz1