
行数は異なるが列数は同じである 2 つの txt ファイルから特定の列を結合したいと思います (以下を参照)。
file1:
xyz desc1 12
uvw desc2 55
pqr desc3 12
file2:
xyz desc1 56
uvw desc2 88
Preferred output:
xyz desc1 12 56
uvw desc2 55 88
pqr desc3 12 0
現在、私は awk を使用して paste コマンドを次のように使用しています。
paste <(awk '{print $1}' file1) <(awk '{print $2}' file1) <(awk '{print $3}' file1) <(awk '{print $3}' file2)
しかし、これは重複する列のみを結合するようです。awk で行自体を省略するのではなく、ゼロを挿入する方法はありますか?
出力ファイルに 102 列が含まれるように、100 個のファイルを結合する必要があります。
答え1
列の順序が重要な場合、つまり同じファイルの数字を同じ列に保持する必要がある場合は、異なるファイルを読み取るときにパディングを追加する必要があります。以下は、GNU awk で機能する方法の 1 つです。
マージ.awk
# Set k to be a shorthand for the key
{ k = $1 SUBSEP $2 }
# First element with this key, add zeros to align it with other rows
!(k in h) {
for(i=1; i<=ARGIND-1; i++)
h[k] = h[k] OFS 0
}
# Remember the data element
{ h[k] = h[k] OFS $3 }
# Before moving to the next file, ensure that all rows are aligned
ENDFILE {
for(k in h) {
if(split(h[k], a) < ARGIND)
h[k] = h[k] OFS 0
}
}
# Print out the collected data
END {
for(k in h) {
split(k, a, SUBSEP)
print a[1], a[2], h[k]
}
}
ここにいくつかのテストファイルがあります: f1
、、f2
およびf3
:f4
$ tail -n+1 f[1-4]
==> f1 <==
xyz desc1 21
uvw desc2 22
pqr desc3 23
==> f2 <==
xyz desc1 56
uvw desc2 57
==> f3 <==
xyz desc1 87
uvw desc2 88
==> f4 <==
xyz desc1 11
uvw desc2 12
pqr desc3 13
stw desc1 14
arg desc2 15
テスト1
awk -f merge.awk f[1-4] | column -t
出力:
pqr desc3 23 0 0 13
uvw desc2 22 57 88 12
stw desc1 0 0 0 14
arg desc2 0 0 0 15
xyz desc1 21 56 87 11
テスト2
awk -f merge.awk f2 f3 f4 f1 | column -t
出力:
pqr desc3 0 0 13 23
uvw desc2 57 88 12 22
stw desc1 0 0 14 0
arg desc2 0 0 15 0
xyz desc1 56 87 11 21
編集:
出力をタブで区切る必要がある場合は、それに応じて出力フィールド区切り文字を設定します。
awk -f merge.awk OFS='\t' f[1-4]
答え2
これを試して:
$ awk '
FNR == NR { a[$1,$2] = $3; next }
{
print $0,(($1,$2) in a) ? a[$1,$2] : "0"
}
' file2 file1
xyz desc1 12 56
uvw desc2 55 88
pqr desc3 12 0
答え3
少し長いですが、機能します:
$ cat file1 file2 | awk '{a[$1FS$2]=a[$1FS$2]FS$3; b[$1FS$2]++} END {for (i in b) max=max<b[i]?b[i]:max; for (i in a) {printf "%s %s", i, a[i]; for (j=b[i]; j<max; j++) printf "%s0", FS printf "%s", RS}}'
pqr desc3 12 0
xyz desc1 12 56
uvw desc2 55 88
awk ブロックは次のようにフォーマットできます。
awk '{a[$1FS$2]=a[$1FS$2]FS$3; b[$1FS$2]++}
END {for (i in b) max=max<b[i]?b[i]:max
for (i in a) {printf "%s%s%s", i, FS, a[i]
for (j=b[i]; j<max; j++) printf "%s0", FS
printf "%s", RS}
}'
アイデアは、すべてのファイルを印刷し、配列内の繰り返し値をキャッチすることですa[$1 $2]
。また、にはペア ( 、 ) が出現したb[$1 $2]
回数が含まれます。$1
$2
ブロックでは、END{}
値をループし、0
要素数から最大要素数まで、不足している値をすべて補完し続けます。