特定の列の複数行のマージ

特定の列の複数行のマージ

次のファイルがあります。

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]

おすすめ記事