我有七個(或八個等)檔案具有相同的行數。
文件1
1.001
1.002
1.003
1.004
文件2
2.001
2.002
2.003
2.004
文件3
3.001
3.002
3.003
3.004
ETC。
期望的輸出:
1.001;2.001;3.001;4.001;5.001;6.001;7.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004
如何在 awk 中使用簡短的腳本來做到這一點?
答案1
正如 Steeldriver 所說,做到這一點的合理方法是paste
:
$ paste -d';' file*
1.001;2.001;3.001;4.001;5.001;6.001;7.001;8.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002;8.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003;8.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004;8.004
但是,如果您必須使用awk
:
$ awk '{a[FNR]=a[FNR](FNR==NR?"":";")$0} END{for (i=1;i<=FNR;i++) print a[i]}' file*
1.001;2.001;3.001;4.001;5.001;6.001;7.001;8.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002;8.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003;8.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004;8.004
awk 腳本將所有資料保存在記憶體中。如果文件很大,這可能是一個問題。但是,對於這個任務來說,paste
無論如何都更好、更簡單。
怎麼運作的
在此腳本中,a
有一個數組,它a[i]
是 line 的輸出i
。當我們閱讀每個後續文件時,我們將 line 的新資訊附加i
到a[i]
.讀取完文件後,我們印出 中的值a
。更詳細地說:
a[FNR]=a[FNR](FNR==NR?"":";")$0
FNR
是我們正在讀取的目前檔案的行號,$0
是該行的內容。這段程式碼加入$0
的末尾a[FNR]
。除非我們仍在讀取第一個文件,否則我們會在 之前添加一個分號$0
。這是使用看起來複雜的三元語句來完成的:(FNR==NR?"":";")
。這其實只是一個 if-then-else 指令。如果我們正在讀取第一個文件,即 ifFNR==NR
,那麼它會傳回一個空字串""
。如果不是,則回傳一個分號;
。END{for (i=1;i<=FNR;i++) print a[i]}
當我們讀完所有文件後,這會列印我們在 array 中累積的數據
a
。
答案2
POSIX awk;這適用於任意數量的文件,並且文件甚至不必具有相同數量的行。該腳本將繼續運行,直到所有檔案都超出行數:
BEGIN {
do {
br = ch = 0
while (++ch < ARGC)
if (getline < ARGV[ch]) {
printf ch < ARGC - 1 ? $0 ";" : $0 RS
br = 1
}
} while (br)
}