所以我有两个文件,文件 1 如下所示:
RR1.out RR2.out RR3.out RR4.out RR5.out RR6.out
45.7597 45.7646 45.4453 45.4448 45.2081 45.1785
55.5468 55.5269 55.3789 55.3598 55.4377 55.4591
51.4768 51.4792 51.6955 51.6972 51.5128 51.5245
54.9851 54.9957 54.9617 54.9688 54.9465 54.9579
45.4459 45.4623 46.1614 46.1679 46.0906 46.0488
文件 2 如下所示:
file Gibbs kcal rel pop weighted
RR2.out -1752.142111 -1099486.696073 0.000000 1.0000 0.4591
RR1.out -1752.141887 -1099486.555511 0.140562 0.7890 0.3622
RR4.out -1752.140564 -1099485.725315 0.970758 0.1947 0.0894
RR3.out -1752.140319 -1099485.571575 1.124498 0.1502 0.0689
RR5.out -1752.138532 -1099484.450215 2.245858 0.0227 0.0104
RR6.out -1752.138493 -1099484.425742 2.270331 0.0218 0.0100
我希望能够让脚本获取文件 1 第 1 列中的第一个值,在文件 2 的第 1 列中找到该值,在文件 2 中的第 6 列中找到与该值位于同一行的值,然后乘以文件 1 第 1 列中的其余数字按该值,打印到新文件,然后重复,直到用完列。然后,新数据应全部合并到与文件 1 中相同的标题下(RR1.out 等)。
例如:要查找的第一个值是 RR1.out,它位于文件 2 第 1 列的第 3 行中,第 3 行第 6 列中的值是 0.3622。因此,file1 中的 column1 中的其余值应乘以 0.3622 并打印到新文件中。
我运行它的超级计算机可以使用多种语言,但我最熟悉的是 bash 和 awk。 Python也可以在超级计算机上运行。
任何关于从哪里开始的建议将不胜感激。我相信 awk 的某种数组函数可以用于查找值,但我不确定如何在文档之间传输变量。
根据要求,输出应该类似于
RR1.out RR2.out RR3.out RR4.out RR5.out RR6.out
16.57416 21.01052 3.13118 4.06276 0.47016 0.45178
20.11905 25.49239 3.81560 4.94916 0.57655 0.55459
18.64489 23.63410 3.56181 4.62172 0.53573 0.51524
19.91560 25.24852 3.78686 4.91421 0.57144 0.54957
16.46050 20.87174 3.18052 4.12741 0.47934 0.46048
最终脚本需要能够处理 file1 中超过 30 列和 100 行的大量数据。 file1 中的列数和行数是可变的,最多为 100 列和 100 行。
答案1
为了多样化,这里有一个主要使用浮点运算的解决bash
方案bc
。
#!/usr/bin/env bash
# r is an associative array of weights, indexed by column name
declare -A r
source <(awk '{ print "r[\"" $1 "\"]=" $6}' <( tail +2 file2))
hdr=
while read line
do
if ! [ $hdr ]
then
hdr=($line)
set -- $line
for h do
printf '%-12s ' "$h"
done
printf '\n'
else
set -- $line
for h in ${hdr[@]}
do
coef=${r[$h]}
printf '%-11.5f ' \
$(bc <<< "scale=6; $1 * $coef")
shift
done
printf '\n'
fi
done < file1
6x5 样本输出:
RR1.out RR2.out RR3.out RR4.out RR5.out RR6.out
16.57416 21.01053 3.13118 4.06277 0.47016 0.45179
20.11905 25.49240 3.81561 4.94917 0.57655 0.55459
18.64490 23.63410 3.56182 4.62173 0.53573 0.51524
19.91560 25.24852 3.78686 4.91421 0.57144 0.54958
16.46050 20.87174 3.18052 4.12741 0.47934 0.46049
答案2
100x100 的文件并不大,因此不需要任何特殊处理。我一直在想象每列生成不同的输出文件,然后使用粘贴将它们组合起来,但对于一个小的文件来说,这是没有必要的,只需将值存储在数组中就可以了:
$ cat tst.awk
BEGIN { OFS = "\t" }
NR==FNR {
key2mult[$1] = $NF
next
}
FNR==1 {
for (colNr=1; colNr<=NF; colNr++) {
colNr2mult[colNr] = key2mult[$colNr]
printf "%s%s", $colNr, (colNr<NF ? OFS : ORS)
}
next
}
{
for (colNr=1; colNr<=NF; colNr++) {
vals[FNR,colNr] = $colNr
}
}
END {
for (rowNr=2; rowNr<=FNR; rowNr++) {
for (colNr=1; colNr<=NF; colNr++) {
printf "%.05f%s", vals[rowNr,colNr] * colNr2mult[colNr], (colNr<NF ? OFS : ORS)
}
}
}
。
$ awk -f tst.awk file2 file1
RR1.out RR2.out
16.57416 21.01053
20.11905 25.49240
18.64490 23.63410
以上是在此输入上运行的:
$ tail -n +1 file1 file2
==> file1 <==
RR1.out RR2.out
45.7597 45.7646
55.5468 55.5269
51.4768 51.4792
==> file2 <==
file Gibbs weighted
RR2.out -1752.142111 0.4591
RR1.out -1752.141887 0.3622
RR4.out -1752.140564 0.0894
使用新的示例输入:
$ awk -f tst.awk file2 file1
RR1.out RR2.out RR3.out RR4.out RR5.out RR6.out
16.57416 21.01053 3.13118 4.06277 0.47016 0.45178
20.11905 25.49240 3.81561 4.94917 0.57655 0.55459
18.64490 23.63410 3.56182 4.62173 0.53573 0.51525
19.91560 25.24853 3.78686 4.91421 0.57144 0.54958
16.46050 20.87174 3.18052 4.12741 0.47934 0.46049
$ awk -f tst.awk file2 file1 | column -s$'\t' -t
RR1.out RR2.out RR3.out RR4.out RR5.out RR6.out
16.57416 21.01053 3.13118 4.06277 0.47016 0.45178
20.11905 25.49240 3.81561 4.94917 0.57655 0.55459
18.64490 23.63410 3.56182 4.62173 0.53573 0.51525
19.91560 25.24853 3.78686 4.91421 0.57144 0.54958
16.46050 20.87174 3.18052 4.12741 0.47934 0.46049