Pet*_*r.O 131 utilities text-processing units
是否有标准工具可以将字节的整数计数转换为人类可读的最大可能单位大小计数,同时将数值保持在 1.00 和 1023.99 之间?
我有我自己的 bash/awk 脚本,但我正在寻找一个标准工具,它可以在许多/大多数发行版中找到......更普遍可用的东西,理想情况下有简单的命令行参数,和/或可以接受管道输入。
以下是我正在寻找的输出类型的一些示例。
1 Byt
173.00 KiB
46.57 MiB
1.84 GiB
29.23 GiB
265.72 GiB
1.63 TiB
Run Code Online (Sandbox Code Playgroud)
这是bytes-human脚本(用于上述输出)
awk -v pfix="$1" -v sfix="$2" 'BEGIN {
split( "Byt KiB MiB GiB TiB PiB", unit )
uix = uct = length( unit )
for( i=1; i<=uct; i++ ) val[i] = (2**(10*(i-1)))-1
}{ if( int($1) == 0 ) uix = 1; else while( $1 < val[uix]+1 ) uix--
num = $1 / (val[uix]+1)
if( uix==1 ) n = "%5d "; else n = "%8.2f"
printf( "%s"n" %s%s\n", pfix, num, unit[uix], sfix )
}'
Run Code Online (Sandbox Code Playgroud)
更新 这是Gilles脚本的修改版本,如对他的回答的评论中所述。(修改为适合我的首选外观)。
awk 'function human(x) {
s=" B KiB MiB GiB TiB EiB PiB YiB ZiB"
while (x>=1024 && length(s)>1)
{x/=1024; s=substr(s,5)}
s=substr(s,1,4)
xf=(s==" B ")?"%5d ":"%8.2f"
return sprintf( xf"%s\n", x, s)
}
{gsub(/^[0-9]+/, human($1)); print}'
Run Code Online (Sandbox Code Playgroud)
Gil*_*il' 142
不,没有这样的标准工具。
自 GNU coreutils 8.21(2013 年 2 月,因此尚未出现在所有发行版中)以来,在非嵌入式 Linux 和 Cygwin 上,您可以使用numfmt. 它不会产生完全相同的输出格式(从 coreutils 8.23 开始,我认为您不能在小数点后获得 2 位数字)。
$ numfmt --to=iec-i --suffix=B --padding=7 1 177152 48832200 1975684956
1B
173KiB
47MiB
1.9GiB
Run Code Online (Sandbox Code Playgroud)
自 coreutils 7.5(2009 年 8 月,因此出现在现代非嵌入式 Linux 发行版中)以来,许多较旧的 GNU 工具可以生成这种格式,并且GNU sort 可以使用单位对数字进行排序。
我发现你的代码有点复杂。这是一个更清晰的 awk 版本(输出格式不完全相同):
awk '
function human(x) {
if (x<1000) {return x} else {x/=1024}
s="kMGTEPZY";
while (x>=1000 && length(s)>1)
{x/=1024; s=substr(s,2)}
return int(x+0.5) substr(s,1,1)
}
{sub(/^[0-9]+/, human($1)); print}'
Run Code Online (Sandbox Code Playgroud)
don*_*sti 88
从 v. 开始8.21,coreutils包括numfmt:
numfmt读取各种表示形式的数字并根据要求重新格式化它们。
最常见的用法是将数字与人类表示相互转换 。
例如
printf %s\\n 5607598768908 | numfmt --to=iec-i
Run Code Online (Sandbox Code Playgroud)
5.2Ti
此处介绍了各种其他示例(包括过滤、输入/输出处理等)。
另外,从coreutilsv. 开始8.24,numfmt可以处理多个字段范围规范类似于 的字段cut,并且支持使用--format选项
eg设置输出精度
numfmt --to=iec-i --field=2,4 --format='%.3f' <<<'tx: 180000 rx: 2000000'
Run Code Online (Sandbox Code Playgroud)
发送:175.782Ki 接收:1.908Mi
Cam*_*tin 34
这是一个 bash-only 选项,没有bc或任何其他非内置,+十进制格式和二进制单位。
# Converts bytes value to human-readable string [$1: bytes value]
bytesToHumanReadable() {
local i=${1:-0} d="" s=0 S=("Bytes" "KiB" "MiB" "GiB" "TiB" "PiB" "EiB" "YiB" "ZiB")
while ((i > 1024 && s < ${#S[@]}-1)); do
printf -v d ".%02d" $((i % 1024 * 100 / 1024))
i=$((i / 1024))
s=$((s + 1))
done
echo "$i$d ${S[$s]}"
}
Run Code Online (Sandbox Code Playgroud)
例子:
$ bytesToHumanReadable 123456789
117.73 MiB
$ bytesToHumanReadable 1000000000000 # '1TB of storage'
931.32 GiB # 1TB of storage
$ bytesToHumanReadable
0 Bytes
$ bytesToHumanReadable 9223372036854775807
7.99 EiB
Run Code Online (Sandbox Code Playgroud)
在任何版本的 Bash 上都应该表现良好(包括 MSYSGit 的 Bash for Windows)。
通过linux - 是否有用于字节计算的命令行计算器?- Stack Overflow,我发现了GNU Units - 尽管 SO 页面上没有示例;因为我没有看到它列在这里,所以这里有一个关于它的小说明。
首先,检查单位是否存在:
$ units --check-verbose |grep byte
doing 'byte'
$ units --check-verbose |grep mega
doing 'megalerg'
doing 'mega'
$ units --check-verbose |grep mebi
doing 'mebi'
Run Code Online (Sandbox Code Playgroud)
鉴于它们是,做一个转换 -printf格式说明符被接受来格式化数字结果:
$ units --one-line -o "%.15g" '20023450 bytes' 'megabytes' # also --terse
* 20.02345
$ units --one-line -o "%.15g" '20023450 bytes' 'mebibytes'
* 19.0958499908447
$ units --one-line -o "%.5g" '20023450 bytes' 'mebibytes'
* 19.096
Run Code Online (Sandbox Code Playgroud)
这是一个完全重写,灵感来自 Peter.O 的 Gilles awk 脚本的修改版本。
变化:
代码:
bytestohuman() {
# converts a byte count to a human readable format in IEC binary notation (base-1024), rounded to two decimal places for anything larger than a byte. switchable to padded format and base-1000 if desired.
local L_BYTES="${1:-0}"
local L_PAD="${2:-no}"
local L_BASE="${3:-1024}"
BYTESTOHUMAN_RESULT=$(awk -v bytes="${L_BYTES}" -v pad="${L_PAD}" -v base="${L_BASE}" 'function human(x, pad, base) {
if(base!=1024)base=1000
basesuf=(base==1024)?"iB":"B"
s="BKMGTEPYZ"
while (x>=base && length(s)>1)
{x/=base; s=substr(s,2)}
s=substr(s,1,1)
xf=(pad=="yes") ? ((s=="B")?"%5d ":"%8.2f") : ((s=="B")?"%d":"%.2f")
s=(s!="B") ? (s basesuf) : ((pad=="no") ? s : ((basesuf=="iB")?(s " "):(s " ")))
return sprintf( (xf " %s\n"), x, s)
}
BEGIN{print human(bytes, pad, base)}')
return $?
}
Run Code Online (Sandbox Code Playgroud)
测试用例(如果您想查看输出):
bytestohuman 1; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 500; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1023; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1024; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1500; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 500 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1023 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1024 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1500 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000000 no 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 500 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1023 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1024 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1500 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000000 yes; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 500 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1023 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1024 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 1500 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
bytestohuman 150000000000000000000 yes 1000; echo "${BYTESTOHUMAN_RESULT}.";
Run Code Online (Sandbox Code Playgroud)
享受!
perlCPAN上有几个模块:Format::Human::Bytes和Number::Bytes::Human,后者更完整一些:
$ echo 100 1000 100000 100000000 |
perl -M'Number::Bytes::Human format_bytes' -pe 's/\d{3,}/format_bytes($&)/ge'
100 1000 98K 96M
$ echo 100 1000 100000 100000000 |
perl -M'Number::Bytes::Human format_bytes' -pe 's/\d{3,}/
format_bytes($&,bs=>1000, round_style => 'round', precision => 2)/ge'
100 1.00k 100k 100M
Run Code Online (Sandbox Code Playgroud)
反过来:
$ echo 100 1.00k 100K 100M 1Z |
perl -M'Number::Bytes::Human parse_bytes' -pe '
s/[\d.]+[kKMGTPEZY]/parse_bytes($&)/ge'
100 1024 102400 104857600 1.18059162071741e+21
Run Code Online (Sandbox Code Playgroud)
注意:该功能parse_bytes()是在 0.09 (2013-03-01) 版本中添加的
| 归档时间: |
|
| 查看次数: |
61615 次 |
| 最近记录: |