我有一个号码12343423455.23353
。我想用千位分隔符格式化数字。所以输出将是12,343,423,455.23353
答案 0 :(得分:33)
$ printf "%'.3f\n" 12345678.901
12,345,678.901
答案 1 :(得分:8)
<强> TL;博士强>
使用numfmt
,如果 GNU 实用程序可用,例如在Linux上默认情况下:
numfmt --grouping 12343423455.23353 # -> 12,343,423,455.23353 in locale en_US
否则,使用printf
并将'
字段标记包含在 shell函数 中保留数量输入小数位(不会硬编码输出小数位数)。
groupDigits 12343423455.23353 # -> 12,343,423,455.23353 in locale en_US
groupDigits()
的定义,该定义还支持多个输入数字。 涉及子广告的特殊替代方案 还保留输入小数位数(假设输入小数点是.
或,
):
(n=$(</dev/stdin); f=${n#*[.,]}; printf "%'.${#f}f\n" "$n") <<<12343423455.23353
$n
的速度明显更快,但模块化程度更低:n=12343423455.23353; (f=${n#*[.,]} printf "%'.${#f}f\n" "$n")
或者,考虑使用我的Linux / macOS grp
CLI (可以npm install -g grp-cli
安装):
grp -n 12343423455.23353
在所有情况下都有警告;见下文。
Ignacio Vazquez-Abrams's answer包含与printf
一起使用的关键指针:'
字段标记(在%
之后)格式化带有活动区域设置的数字&#39; s分离器:
man printf
(man 1 printf
)本身不包含此信息:实用程序 / shell builtin printf
最终调用库函数< / em> printf()
,只有man 3 printf
能够全面了解支持的格式。LC_NUMERIC
和间接LANG
或LC_ALL
控制有关数字格式的活动区域设置。numfmt
和printf
都尊重活动区域设置,包括千位分隔符和小数点(&#34;小数点&#34;)。printf
,就像在Ignacio的回答中一样,要求您硬编码 输出小数位数,而不是比保留输入有多少小数位;这是groupDigits()
以下克服的限制。printf "%'.<numDecPlaces>f"
确实比numfmt --grouping
有一个优势,但是:
numfmt
仅接受十进制号码,而printf
&#39; s %f
也接受十六进制整数(例如, 0x3e8
)和十进制数字科学记数法(例如1e3
)。 没有分组的区域设置:根据定义,某些区域设置(尤其是C
和POSIX
不应用分组,因此使用'
没有在那种情况下的效果。
跨平台的实际区域设置不一致:
(LC_ALL='de_DE.UTF-8'; printf "%'.1f\n" 1000) # SHOULD yield: 1.000,0
1.000,0
。1000,0
- 没有分组(!)。numfmt
或printf
时,它会:
(LC_ALL='lt_LT.UTF-8'; printf "%'.1f\n" 1000,1) # -> '1 000,1'
可移植性:POSIX不要求 printf
utility(而不是C printf()
库函数)支持浮点格式字符,例如%f
,因为POSIX [-like] shell只是整数;但实际上,我并不知道任何没有的shell /平台。
舍入错误和溢出:
numfmt
和printf
时,会发生往返转换(字符串 - >数字 - >字符串),这会导致舍入错误;换句话说:使用数字分组重新格式化会导致数字不同。f
来使用IEEE-754 double-precision floating-point values,只有最多15 significant digits (与小数点位置无关的数字)保证被准确保存(尽管对于特定数字,它可以使用更多数字)。 在实践中,numfmt
和 GNU printf
可以准确处理更多;见下文。如果有人知道如何以及为什么,请告诉我。 numfmt
和printf
之间有所不同,而{strong}之间的会有所不同跨平台实施;例如: <强> printf
强>:
[已在coreutils 8.24中修复,根据@pixelbeat] 从20位有效数字开始,值溢出(!) - 可能是一个错误(从GNU coreutils 8.23开始):< / p>
numft
相比之下,过大的数字会默认生成错误。
<强> # 20 significant digits cause quiet overflow:
$ (fractPart=0000000000567890; num="1000.${fractPart}"; numfmt --grouping "$num")
-92.23372036854775807 # QUIET OVERFLOW
强>:
Linux printf
最多可处理20位有效数字 ,而BSD / macOS实施仅限于17:
printf
Linux版本似乎永远不会溢出,而BSD / macOS版本报告错误的数字太大。
# Linux: 21 significant digits cause rounding error:
$ (fractPart=00000000005678901; num="1000.${fractPart}"; printf "%'.${#fractPart}f\n" "$num")
1,000.00000000005678902 # ROUNDING ERROR
# BSD/macOS: 18 significant digits cause rounding error:
$ (fractPart=00000000005678; num="1000.${fractPart}"; printf "%'.${#fractPart}f\n" "$num")
1,000.00000000005673 # ROUNDING ERROR
:groupDigits()