Shell-Script
如何將多個關聯文件的行連接成一行,並將其附加到輸出文件
我有幾個文件命名
BC**-tmp1.tsv
為爆炸輸出的第一次迭代,而其他文件命名BC**-tmp2.tsv
為第二次迭代。文件範例
BC02-tmp1.tsv
(分隔符 :\t
):BC02 Aaa 2712 94 0 99.073 2053209 CP023507.1 1597 A BC02 Bbb 2712 94 0 99.073 2053209 CP023507.1 1597 B BC02 Ccc 2712 94 0 99.073 2053209 CP023507.1 1597 C BC02 Ddd 2712 94 0 99.073 2053209 CP023507.1 1597 D
文件範例
BC02-tmp2.tsv
(分隔符 :\t
):BC02 Eee 2712 94 0 99.073 2053209 CP023507.1 1597 E BC02 Fff 2712 94 0 99.073 2053209 CP023507.1 1597 F BC02 Ggg 2712 94 0 99.073 2053209 CP023507.1 1597 G BC02 Hhh 2712 94 0 99.073 2053209 CP023507.1 1597 H
我的目標是以特定方式逐對(迭代 1 + 迭代 2)連接所有這些文件。
結果範例
BC02
與最終文件中的範例:BC02 Aaa 2712 94 0 99.073 2053209 CP023507.1 1597 A B C BC02 Eee 2712 94 0 99.073 2053209 CP023507.1 1597 E F G
所以更準確地說,我想列印(在同一行)
BC**-tmp1.tsv
文件的第一行,然後是第二行的最後一列,然後是第三行的最後一列,然後是BC**-tmp2.tsv
文件的第一行,然後是第二行的最後一列,然後是第三行的最後一列。對於每對條碼。注意:第二次迭代文件並不總是存在。
到目前為止,我設法在一個 shell
for
循環中收集了相關文件,但我不知道如何做剩下的:touch template.tsv for bla in *-tmp1.tsv; do r="$(basename -s "-tmp1.tsv" $bla)" awk 'FNR==1' $bla >> template.tsv awk 'FNR==1' $r-tmp2.tsv >> template.tsv; done
你知道怎麼做嗎 ?
編輯更簡單的輸入/輸出:
輸入:
$ head BC02-tmp*.tsv ==> BC02-tmp1.tsv <== a b B a c C a d D a e E ==> BC02-tmp2.tsv <== a w W a x X a y Y a z Z
輸出:
a b B C D a w W X Y
假設您的輸入不包含邊緣情況,則與
awk
程序相關的以下 shell 循環應該執行以下操作:for f in BC*-tmp1.tsv do f2="${f/%tmp1.tsv/tmp2.tsv}" if [[ ! -f $f2 ]]; then f2=""; fi awk 'BEGIN{FS=OFS="\t"} FNR==1{for (i=1;i<NF;i++) printf "%s%s",(NR==FNR&&i==1?"":OFS),$i} FNR<=3{printf "%s%s",OFS,$NF} END{printf "%s",ORS}' "$f" "$f2" >> template.tsv done
這將遍歷所有
tmp1.tsv
文件並為文件生成相應的文件名tmp2.tsv
。如果第二個文件不存在,則文件名將設置為空字元串。然後它會呼叫一個
awk
包含兩個關聯 TSV 文件的程序,這些文件將列印 - 都在同一行
- 每個輸入文件的第一行的所有欄位,不包括最後一個欄位(但在第二個輸入文件的情況下,前面有一個額外的 OFS,其特徵是
FNR
,每個文件行計數器,不再等於NR
,全域行櫃檯),- 每行的最後一個欄位,直到第 3 行,
- 當沒有輸入文件時,關閉記錄分隔符(預設為換行符)
並將輸出附加到
template.tsv
. 如果第二個模板文件不存在,這也將起作用,因為空字元串令牌首先不會被辨識為輸入文件awk
,因此END
列印換行符的部分將在第一個文件之後到達。