UNIX 貼上列並為所有缺失值插入零

UNIX 貼上列並為所有缺失值插入零

我想合併兩個包含不同行數但列數相同的 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 <(awk '{print $1}' file1) <(awk '{print $2}' file1) <(awk '{print $3}' file1) <(awk '{print $3}' file2) 

但這似乎只合併重疊的列。 awk 有沒有辦法插入零而不是省略行本身?

我需要將 100 個檔案合併在一起,這樣我的輸出檔案將包含 102 個欄位。

答案1

如果列順序很重要,即來自相同文件的數字應保留在同一列中,則需要在讀取不同文件時添加填充。這是使用 GNU awk 的一種方法:

合併.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]
  }
}

以下是一些測試文件:f1f2f3f4

$ 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從元素數量到最大元素數量之間缺失的盡可能多的 s 。

相關內容