打印函数

打印函数

我有一个包含 40,000 行的文件

head flower_all

    0.992957746478873 0.00704225352112677
    0.646410833917366 0.353589166082634
    0.992957746478873 0.00704225352112677
    0.992957746478873 0.00704225352112677
    0.992957746478873 0.00704225352112677
    0.992957746478873 0.00704225352112677
    0.992957746478873 0.00704225352112677
    0.992957746478873 0.00704225352112677
    0.5 0.5

我只想保留 3 位有效数字。我想要的输出:

0.992 0.007
0.646 0.353
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.5 0.5

我该怎么做?

答案1

awk

awk '{ printf("%.3g %.3g\n", $1, $2) }' file

根据给定的数据,这会产生

0.993 0.00704
0.646 0.354
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.5 0.5

请注意,0.00704 有五位小数,但有三位有效数字。

如果您想要精确三位小数,请使用%.3f代替%.3g并得到

0.993 0.007
0.646 0.354
0.993 0.007
0.993 0.007
0.993 0.007
0.993 0.007
0.993 0.007
0.993 0.007
0.500 0.500

使用 GNU 可以将上面的两种变体推广到可变数量的列awk

awk -v CONVFMT='%.3g' '{ for (i=1; i<=NF; ++i) $i+=0; print }' file

循环$i+=0强制awk将每个字段的值重新格式化为浮点数,它将在考虑到的情况下执行此操作CONVFMT(它或多或少会执行相当于 的操作$i=sprintf(CONVFMT, $i))。


如果你想号码:

awk '{ for (i=1; i<=NF; ++i) $i=sprintf("%.5s", $i); print }' file

这会将数字视为字符串,并在五个字符后将其截断(假设所有数字都小于 10 且大于零),生成

0.992 0.007
0.646 0.353
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.5 0.5

对于稍微更一般的数字切割:

awk '{ for (i=1; i<=NF; ++i) if (match($i,".*\\.[0-9]?[0-9]?[0-9]?")) $i=substr($i,RSTART,RLENGTH); print }' file

循环中的操作会在给定正则表达式匹配结束的位置(如果匹配)削减数字。

答案2

您的数据没有超过 1 的数字。我扩展了源文件以包含一些在点前有更多数字的值:

$ cat infile
0.992957746478873 0.00704225352112677
0.646410833917366 0.353589166082634
0.992957746478873 0.00704225352112677
0.5 0.5
16.258137489137 333444.277775666
16.233399999999 333777.277111111

打印函数

一种可能的解决方案是使用 C 兼容的 printf 函数(awk 有一个):

f 格式(小数点后 3 位(四舍五入))

精确到小数点后 3 位(四舍五入):

$ awk '{ printf("%11.3f %11.3f\n", $1,$2) }' infile
      0.993       0.007
      0.646       0.354
      0.993       0.007
      0.500       0.500
     16.258  333444.278
     16.233  333777.277

请注意,0.992957746478873四舍五入为0.993

g 格式(有效(四舍五入))

3 位(有效)数字的精确计数:

$ awk '{ printf("%9.3g %9.3g\n", $1,$2) }' infile
    0.993   0.00704
    0.646     0.354
    0.993   0.00704
      0.5       0.5
     16.3  3.33e+05
     16.2  3.34e+05

请注意第四位数字的四舍五入(例如 3.34e+05)

字符串(未舍入)

小数点后正好 3 位(不四舍五入)。

使用 GNU awk:

$ gawk '{for(i=1;i<=NF;i++){
         printf( "%12s ",gensub(/([0-9]+\.[0-9]{0,3}).*/, "\\1", "g", $i))};print""}
       ' infile
       0.992        0.007
       0.646        0.353
       0.992        0.007
         0.5          0.5
      16.258   333444.277
      16.233   333777.277

使用 sed (可能更快):

$ sed -E 's/([0-9]+\.[0-9]{1,3})[^ ]*/\1/g' infile
0.992 0.007
0.646 0.353
0.992 0.007
0.5 0.5
16.258 333444.277
16.233 333777.277

相关内容