0

我有一些数据文本文件,其行是带有错误的值,如下所示:

...
6  90.3785794742981 0.0952997386139722
40 1028.46336161948 4.41798447319325
...

第三列是相对于第二列的误差。我想编写一个脚本,以更易于阅读的格式打印它们,即打印具有正确数量有效数字的值并在括号之间的最后两个数字上打印错误,如下所示:

...
6  90.379(95)
40 1028.5(4.4)
...

使用正则表达式来提取数字将无法正常工作,因为处理点有困难,并且因为它会截断数字而不是近似它们,所以我认为我宁愿用 . 检索它们的大小printf并用bc.

我为此编写的代码如下

#! /bin/bash
while read a v verr
do
    ov=`printf %e $v`
    ov=${ov/*e/}
    overr=`printf "%e" $verr`
    overr=${overr/*e/}
dov=$((1-$overr))
v=`echo "scale=0;$v*10^($dov)" | bc -l`
v=`printf %.0f $v`
printf "$a %f(%.0f)\n" `echo "lenght=length($v);$v*10^($((-$dov)))" | bc -l` `echo "$verr*10^($dov)" | bc -l`
 done < myfile.txt

我得到的是

6 90.379000(95)
40 1028.500000(44)

我的代码几乎可以工作,除了那些尾随零的出现。

我该如何摆脱它们?仅仅削减它们是不好的,因为它们的数字不是固定的,并且无论最后一个数字实际上是否为零,都将它们全部削减都会产生错误。

4

2 回答 2

0

如果您可以使用 sed 命令,则可以在 printf 之后添加 sed 语句以删除尾随零:

printf "$a %f(%.0f)\n" `echo "lenght=length($v);$v*10^($((-$dov)))" | bc -l` `echo "$verr*10^($dov)" | bc -l` | sed 's/00*(/(/'
于 2012-10-12T15:47:22.367 回答
0

以下代码有效。

#! /bin/bash
while read a v verr
do
ov=`printf %e $v`
    ov=${ov/*e/}
    overr=`printf %e $verr`
overr=${overr/*e/}
dov=$((1-$overr))
v=`echo "scale=0;$v*10^($dov)" | bc -l`
v=`printf %.0f $v`

if [ $dov -gt 0 ]; then
    # remember bc doesn't understand numbers in scientific notation,
    # therefore we need to convert such numbers in regular notation.
    u=`echo ${u} | sed 's/[eE]/\\*10\\^/' | sed 's/+//'`
    verr=`echo ${verr} | sed 's/[eE]/\\*10\\^/' | sed 's/+//'`

    u=`echo "$v*10^($((-$dov)))" | bc -l`
    if [ $overr -eq 0 ]; then
    uerr=`echo "$verr*10^($dov - 1)" | bc -l`
    printf "$a\t%.${dov}f(%.1f)\n" $u $uerr>>$s
    else
    uerr=`echo "$verr*10^($dov)" | bc -l`
    printf "$a\t%.${dov}f(%.0f)\n" $u $uerr>>$s
    fi
else
    echo $a "${v}(${verr})E$ov">>$s
fi
done < $f

它打印我想要格式化的值。第一种情况测试是否需要以指数表示法来表示结果以便获得正确的有效数字,第二种情况测试是否应该在错误中添加一个点。

我没有测试底部的第三行代码,因为我现在不需要它,所以要小心,因为它可能不起作用。

编辑:我插入了两个 sed 调用来处理科学记数法数字。

于 2012-10-13T10:20:29.073 回答