我有几个文件命名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
,然后是第二行的最后一列,然后是第三行的最后一列。每对条形码也是如此。
笔记:第二个迭代文件并不总是存在。
到目前为止,我设法在 shellfor
循环中收集相关文件,但我不知道如何执行其余操作:
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
答案1
假设您的输入不包含边缘情况,则与程序连接的以下 shell 循环awk
应该执行以下操作:
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
打印换行符的部分将在第一个文件之后到达。