配列を行列に結合 - セル間に区切り記号を追加する

配列を行列に結合 - セル間に区切り記号を追加する

両方のファイルをマージし、両方のファイルの2番目の列を追加したいと思います。

ファイル1.

001    A
002    B
003    C
004    D

ファイル2.

002    D
003    D
005    E
006    F

以下のようにファイル3にマージする必要があります。

001    A
002    B D
003    C D
004    D
005    E
006    F

私はandreatshが提案したこのコマンドを試しました。AWKを使用して2つのファイルをマージし、2番目の列を追加します。:

$ awk '{ z[$1]=z[$1]$2 } END { for (i in z) print i, z[i] }' file1  file2
002 BD
003 CD
004 D

など...

かなり似ていますが、文字間にスペースを追加するにはどうすればよいですか?

たとえば、最初の行に「BD」を使用する代わりに「BD」を使用します。

答え1

はい、Awkを使用して実行できますが、これを行うためにJoinが作成されました。

join -a1 -a2 file1 file2

特定のサンプルの出力:

001 A
002 B D
003 C D
004 D
005 E
006 F

を実行する前にファイルをソートする必要がありますjoin。シェルがそれをサポートしている場合は、次のコマンドを使用して1つの手順で実行できます。プロセスの交換:

join -a1 -a2 <(sort file1) <(sort file2)

答え2

正しいツールはjoin実際にクワジモドが示すようにしかし、いくつかの変更を加えて、同じawkコマンドを使用することもできます。

$  awk '{ z[$1]=z[$1]" "$2 } END { for (i in z) print i, z[i] }' file1  file2
002  B D
003  C D
004  D
005  E
006  F
001  A

ちょうどz[$1]=z[$1]$2に変更しましたz[$1]=z[$1]" "$2

答え3

004 Dテストする不明瞭なケースがあるようにfile2に追加しました。これを考慮すると、次のいずれかです。

$ sort -k1,1 -s file1 file2 |
awk '
    $1 != prev { if (NR>1) print ""; printf "%s", $1; prev=$1 }
    { printf " %s", $2 }
    END { print "" }
'
001 A
002 B D
003 C D
004 D D
005 E
006 F

またはこれ:

$ sort -k1,1 -s file1 file2 |
awk '
    $1 != prev{if (NR>1) print ""; printf "%s", $1; prev=$1; delete seen }
    !seen[$2]++ { printf " %s", $2 }
    END { print "" }
'
001 A
002 B D
003 C D
004 D
005 E
006 F

同じキーの重複値をどのように処理するかによって異なります。必要なだけファイルを一覧表示できますsort。上記は、GNUソートが-s同じキーの入力順序を維持していると仮定しています。その順序がなく、実際に必要な場合は、単純な選択肢があります。必要に応じて、ABCなどが各入力ファイルに表示される順序ではなく、常に各出力行にアルファベット順に表示されるように簡単な調整を実行することもできます。たとえば、次のようになります。

$ head file*
==> file1 <==
001    A
002    E
003    F
004    D

==> file2 <==
002    D
003    D
004    D
005    E
006    F

==> file3 <==
001    A
002    E
003    C
004    D

$ sort -s file* | awk '$1 != prev{if (NR>1) print ""; prev=$1; delete seen; printf "%s", $1} !seen[$2]++{printf " %s", $2} END{print ""}'
001 A
002 D E
003 C D F
004 D
005 E
006 F

関連情報