将 csv 中的许多值四舍五入到小数点后 3 位(printf ?)

R 9*_*000 5 csv printf paste

我有一个像这样的粘贴命令 paste -d , file1.csv file2.csv file3.csv

file2.csv 包含这样的数字

0.2
0.3339
0.111111
Run Code Online (Sandbox Code Playgroud)

我希望 file2.csv 中的值具有 3 位小数,如下所示:

0.200
0.334
0.111
Run Code Online (Sandbox Code Playgroud)

对于一个值,这是有效的:

printf "%.3f" "0.3339"->0.334

但对于 file2.csv 中的多个值,这不起作用:

paste -d , file1.csv <(printf %s "%.3f" "$(< file2.csv)") file3.csv

也许有一个好的解决方案?

Kus*_*nda 14

有一个名为 的 GNU 实用程序numfmt,它是 GNU coreutils 工具集合的一部分,看起来在这里很有用。它允许您格式化数值,以下命令将file2.csv使用printf格式字符串%.3f(“精度为三位小数的浮点值”)来格式化所有值。格式化的值将打印在标准输出上:

$ numfmt --format=%.3f <file2.csv
0.200
0.334
0.112
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它默认使用“从零开始”舍入,但这可以通过以下方式更改--round=nearest

$ numfmt --format=%.3f --round=nearest <file2.csv
0.200
0.334
0.111
Run Code Online (Sandbox Code Playgroud)

paste您可以使用进程替换将其插入命令中,如下所示:

paste -d , file1.csv <( numfmt --format=%.3f --round=nearest <file2.csv ) file3.csv
Run Code Online (Sandbox Code Playgroud)

如果您的文件是一个不“简单”的 CSV 文件,即它可能包含带引号的字段,那么您可能需要使用支持 CSV 的工具,例如Miller ( mlr) 来处理数据。下面使用 Miller 表达式中的函数重新创建了numfmt上面的第二个示例(该函数采用格式字符串):fmtnum()putprintf

$ mlr --csv -N put '$1 = fmtnum($1, "%.3f")' file2.csv
0.200
0.334
0.111
Run Code Online (Sandbox Code Playgroud)

--csv选项-N使 Miller 将输入(并写入输出)作为无标头 CSV 读取。


Dop*_*oti 5

你很接近;你只需要告诉printf小数点右边的零填充:

$ cat 736678.txt
0.2
0.3339
0.111111
$ for value in $( cat 736678.txt ); do printf "%.3f\n" "$value"; done
0.200
0.334
0.111
Run Code Online (Sandbox Code Playgroud)

格式字符串的%.3f意思是“在该点右侧精确保留三位小数的浮点数”。

  • `printf "%.03f\n" $( cat 736678.txt )` 也有效。 (2认同)
  • 我总是忘记“printf”会迭代以消耗额外的输入。 (2认同)