对带有 KB/MB/GB/TB/PB... 后缀的数字求和

对带有 KB/MB/GB/TB/PB... 后缀的数字求和

我正在努力寻找一种方法来总结一行数字。

我有以下代码。

lshw -class disk -class storage | grep size: | cut -d "(" -f2 | cut -d ")" -f1

这给了我结果

2TB                         
2TB
2TB
2TB
2TB
2TB

在我的另一台机器上:

500GB                       
1TB
1TB

有没有办法总结这些?我需要保留 GB 或 TB

我完全可以用 GB 来表示,或者只在有超过 2 个结果时才将这些结果相加?我有多台机器,我应该在其中运行此命令。有些有 5 个硬盘,有些只有 1 个。

答案1

使用xmljson输出格式提供的工具来解析可用的工具可能会更容易:

lshw -quiet -class disk -class storage -xml |
  xmlstarlet sel -t -v //size -n |
  paste -sd + - |
  bc |
  numfmt --to=si --suffix=B

格式:

lshw -quiet -class disk -class storage -json |
  jq '[.children[]|.size]|add' |
  numfmt --to=si --suffix=B

即使您没有xml/json解析工具,以这些格式输出仍然是更好的选择,因为您可以获得确切的字节数,因此在从/到人类可读格式转换时不会丢失信息。

然后,您可以恢复到一些基于启发式的解析,例如默认输出格式。使用 GNU grep

lshw -quiet -class disk -class storage -json |
  grep -Po '"size" : \K\d+' |
  paste -sd + - |
  bc |
  numfmt --to=si --suffix=B

--round=nearest向 GNU添加选项numfmt(自 8.21 (2013) 起在 GNU coreutils 中)以舍入到最接近的数字而不是向上舍入。另请参阅--format=%.3f以获得更高的精度。

答案2

sed+numfmt解决方案:

lshw -class disk -class storage \
| sed -n '/size:/ s/.*(\([0-9]*.*[KMGT]\)B)/\1/p' \
| numfmt --from si | paste -sd+ - | bc | numfmt --to si --suffix B

paste -sd+ - | bc也可以替换为awk '{ sum+=$1 }END{ print sum }'

相关内容