我正在尝试找到SCALEFACTOR
基本上是10000/(sum of 4th column in a file)
.如何从输出中获取小数?提前感谢任何帮助。
#!/bin/bash
FILES=/path/to/files/*;
for f in ${FILES}
do
echo $f
COLTOTAL="$(awk '{sum += $4} END {print sum}' $f)"
echo "total: ${COLTOTAL}"
# SCALEFACTOR=`expr 10^5 / $COLTOTAL`
B=10000
SCALEFACTOR=$((B / ${COLTOTAL}))
SCALINGFACTOR=$(echo "100000 / $COLTOTAL" | bc -l
# echo "scale=5; ${SCALEFACTOR}" | bc
echo ${SCALEFACTOR}
awk '{print($1"\t"$2"\t"$3"\t"$4 * ${SCALINGFACTOR})}' $f > $f"_normalized.txt"
done
答案1
for
如果文件中包含空格,则实现循环的方式将会中断。如果没有变量 ,它也能正常工作for f in /path/to/files/*
,因为扩展以循环可以理解的方式发生for
。
一般来说,由于启动新进程确实会消耗资源,因此最好只有一个awk
和 的实例,正如 @jw013 指出的那样,您必须在 shell 外部执行除法,因为sh
和bash
无法进行浮点数学运算。
因为您需要了解文件末尾才能操作每一行,所以您有两个选择:通读每个文件,保存每一行以供第二次通读,或者读取每个文件两次。由于在内存中保存大文件可能会出现问题,因此我选择了第二个选项:
for f in /path/to/files/*; do
echo "$f"
awk '
NR == FNR {
sum += $4;
next;
}
FNR == 1 {
print "total: " sum;
SCALEFACTOR = 10000 / sum;
print SCALEFACTOR;
}
{
printf("%s\t%s\t%s\t%f\n", $1, $2, $3, $4 * SCALEFACTOR);
}' "$f" "$f"
NR == FNR
表示总记录(行)号与当前文件的记录号相同,这意味着您位于第一个文件,手头的任务是确定总和。 next
防止其他子句触发。否则,如果在第二次读取文件的第一行,我们会执行您在awk
两次通话之间所做的事情。对于第二次阅读中的每一行,我们打印四个项目,第四个项目按照您指示的比例缩放。
您可以在第四项上使用标准字符串格式,例如您注释的bc
五级将更%f
改为%.5f
答案2
(echo "scale=5"; echo "100000 / $COLTOTAL") | bc -l