我對 awk 沒有太多經驗,所以我很難克服它的一個問題。我有兩個名為 file1.txt 和 file2.txt 的檔案。文件1.txt:
20 101 1 2 3 4
20 102 5 6 7 8
20 108 3 3 3 3
文件2.txt:
20 100 99 99 99 99
20 101 11 22 33 44
20 103 55 66 77 88
每個檔案中前兩列之後總是有 4 個值。
我想做的是將這些文件合併為一個。我將通過第一列和第二列加入他們。
產生的文件中應有 10 列。前兩列是關鍵列,接下來的 4 列是第一個檔案中的值,最後 4 列來自第二個檔案。
在產生的文件中,第一個文件中與第二個文件不符的每筆記錄(反之亦然)將具有表示缺失值的附加零。
一切都由空格字元分隔。
結果應該是這樣的:
20 100 0 0 0 0 99 99 99 99
20 101 1 2 3 4 11 22 33 44
20 102 5 6 7 8 0 0 0 0
20 103 0 0 0 0 55 66 77 88
20 108 3 3 3 3 0 0 0 0
這是我的 awk 腳本,是我根據在網路上搜尋時找到的腳本進行修改的:
BEGIN {
OFS=" "
}
{
i=$1 OFS $2 #Making key out of first and second field of the first file
}
NR==FNR {
A[i]=$0 #Saving records from first file to an array using first two columns as index
next
}
#Next part assumes that I'm reading file2.txt
i in A {
printf "%s",A[i] #Here, I have a match with first file, and I want to print the joined record I saved from file1.txt
print $3,$4,$5,$6 #In order to print a joined record, after printing record from first file, I'm printing columns from the second file
delete A[i]
next
}
{ #Here I print records from file2.txt that don't have a match with file1.txt, and put zeroes to fill missing values
print 0,0,0,0,$3,$4,$5,$6
}
END { #In the END block I'm printing everything from file1.txt that doesn't have a match and print zeroes aftewards to fill missing values
for (i in A) { printf "%s",A[i]; print 0,0,0,0 }
}
結果按第二列排序,所有缺失值均以零填滿。但是,我目前得到的結果如下所示:
20 100 0 0 0 0 99 99 99 99
11 22 33 443 4
20 103 0 0 0 0 55 66 77 88
20 108 3 3 3 3 0 0 0 0
0 0 0 0 6 7 8
儘管文件沒有排序(我總是可以使用 sort -k 2),但有些行沒有按照我預期的方式打印,而且我無法解釋為什麼它不能正常打印 A 的元素大批。我嘗試過各種方法,例如暫時更改 ORS (完全沒有輸出)或使用 print 而不是 printf (結果看起來也很奇怪)。
由於缺乏經驗,這引發了一些額外的問題:
使用awk來完成這個任務是否合理?我嘗試過使用加入,但最終陷入困境,因為它無法列印末尾帶有換行符的列。也許 Python 腳本會更有用?
考慮到我將使用非常大的文件進行合併,在內存方面使用數組是否合理?
先致謝!
答案1
awk '!second { file1vals[$1 FS $2]=$0 }
second { print (($1 FS $2 in file1vals)?file1vals[$1 FS $2]: $1 FS $2 FS "0 0 0 0") FS $3, $4, $5, $6;
delete file1vals[$1 FS $2]
}
END{ for(x in file1vals) print file1vals[x], "0 0 0 0" }' file1 second=1 file2
只要有足夠的記憶體來載入第一個,這就會起作用文件1進入記憶。
在第一個區塊中!second {...}
,它僅在它是第一個檔案並且我們加載時運行文件1放入第一列和第二列對上的關聯數組中作為數組的鍵。
在第二塊second {...}
,它僅在第二個檔案時運行,我們列印連接的行,這些行在兩個檔案中都有匹配的鍵,否則我們列印鍵和 0,然後列印其餘的列文件2;然後我們也從delete file1vals[$1 FS $2]
兩個檔案中都存在密鑰的陣列中刪除密鑰。
在末尾的最後一個區塊中,我們列印與以下內容相關的剩餘不匹配鍵文件1。