【问题标题】:Convert human readable to bytes in bash将人类可读转换为 bash 中的字节
【发布时间】:2014-12-24 15:26:48
【问题描述】:

所以我试图在 linux 中分析非常大的日志文件,我已经看到了很多与之相反的解决方案,但是记录数据的程序不允许输出格式,因此它只能以人类可读的格式输出(我知道,多么痛苦)。所以问题是:如何使用 awk 之类的东西将人类可读转换为字节:

所以转换这个:

937
1.43K
120.3M

到:

937
1464
126143693

我负担得起,但预计会出现一些舍入误差。

提前致谢。

附:只要它可以提供内联转换,就不必是 awk。

我找到了this,但给出的 awk 命令似乎无法正常工作。它输出类似 534K"0" 的内容。

我还找到了使用 sed 和 bc 的解决方案,但由于它使用 bc,因此效果有限,这意味着它一次只能使用一列,并且所有数据都必须适合 bc,否则会失败。

sed -e 's/K/\*1024/g' -e 's/M/\*1048576/g' -e 's/G/\*1073741824/g' | bc

【问题讨论】:

  • @amdn,谢谢我实际上找到了类似的东西并进行了编辑。该解决方案的唯一问题是它使用 bc,因此它不能很好地分析完整的日志文件。它可以处理同一类型的单列数据。
  • 在该答案的底部有一个不使用 bc 的“一个衬里”

标签: linux bash awk human-readable


【解决方案1】:

使用来自 GNU coreutils 的 numfmt --from=iec

【讨论】:

  • 最佳答案
【解决方案2】:

这是一个理解二进制和十进制前缀的函数,如果需要,它可以很容易地扩展到大型单元:

dehumanise() {
  for v in "${@:-$(</dev/stdin)}"
  do  
    echo $v | awk \
      'BEGIN{IGNORECASE = 1}
       function printpower(n,b,p) {printf "%u\n", n*b^p; next}
       /[0-9]$/{print $1;next};
       /K(iB)?$/{printpower($1,  2, 10)};
       /M(iB)?$/{printpower($1,  2, 20)};
       /G(iB)?$/{printpower($1,  2, 30)};
       /T(iB)?$/{printpower($1,  2, 40)};
       /KB$/{    printpower($1, 10,  3)};
       /MB$/{    printpower($1, 10,  6)};
       /GB$/{    printpower($1, 10,  9)};
       /TB$/{    printpower($1, 10, 12)}'
  done
} 

示例:

$ dehumanise 2K 2k 2KiB 2KB 
2048
2048
2048
2000

$ dehumanise 2G 2g 2GiB 2GB 
2147483648
2147483648
2147483648
2000000000

后缀不区分大小写。

【讨论】:

【解决方案3】:
$ cat dehumanise 
937
1.43K
120.3M

$ awk '/[0-9]$/{print $1;next};/[mM]$/{printf "%u\n", $1*(1024*1024);next};/[kK]$/{printf "%u\n", $1*1024;next}' dehumanise
937
1464
126143692

【讨论】:

  • 谢谢!这也只适用于一列,但它似乎比使用 bc 方法更可靠。
  • @Devon:呵呵。提供一些实际数据,您可能会得到一个实际的解决方案? :)
  • 我接受了这个,因为它运作良好。在接受它之前,我不得不进一步测试它。我所要做的就是在处理不同的列之前添加awk {'print $2'} |(取决于列),对于我的分析,一次分析一列可以正常工作。
  • } 之后不需要;。最后一个next 也不需要,因为它已经位于代码的最后一部分。对于这个简单的代码,另一个 next 也可能被删除,所以应该这样做:awk '/[0-9]$/{print $1} /[mM]$/{printf "%u\n", $1*(1024*1024)} /[kK]$/{printf "%u\n", $1*1024}' file
  • 这不是千兆字节。
【解决方案4】:

存在 Python 工具

$pip install humanfriendly  # Also available as a --user install in ~/.local/bin

$humanfriendly --parse-size="2 KB"
2000
$humanfriendly --parse-size="2 KiB"
2048

【讨论】:

    【解决方案5】:

    awk '函数 pp(p){printf "%u\n",$0*1024^p} /[0-9]$/{print $0}/K$/{pp(1)}/M$/{pp(2)}/G$/{pp(3)}/T$/{pp(4)}/[^0-9KMGT]$ /{打印 0}'

    这是对@starfry 答案的修改。


    让我们分解一下:

    函数 pp(p) { printf "%u\n", $0 * 1024^p }

    定义一个名为 pp 的函数,它接受单个参数 p 并打印 $0 乘以 1024 的 p-th 幂。 %u 将打印该数字的无符号十进制整数。

    /[0-9]$/ { 打印 $0 }

    匹配以数字结尾的行($ 匹配行尾),然后运行{} 内的代码。打印整行 ($0)

    /K$/ { pp(1) }

    匹配以大写字母K 结尾的行,调用函数 pp() 并将 1 传递给它(p == 1)。 注意:当在数学方程式中使用 $0(例如“1.43K”)时,下面只会使用开头的数字(例如“1.43”)。 $0 = "1.43K" 的示例

    $0 * 1024^p == 1.43K * 1024^1 == 1.43K * 1024 = 1.43 * 1024 = 1464.32
    

    /M$/ { pp(2) }

    匹配以大写字母M 结尾的行,调用函数 pp() 并将 2 传递给它(p == 2)。以 $0 == "120.3M" 为例

    $0 * 1024^p == 120.3M * 1024^2 == 120.3M * 1024^2 == 120.3M * 1024*1024 = 120.3 * 1048576 = 126143692.8
    

    等等...对于GT

    /[^0-9KMGT]$/ { 打印 0 }

    不以数字或大写字母 K、M、G 或 T 结尾的行打印“0”。


    示例:

    $ cat dehumanise
    937
    1.43K
    120.3M
    5G
    933G
    12.2T
    bad
    <>
    

    结果:

    $ awk 'function pp(p){printf "%u\n",$0*1024^p} /[0-9]$/{print $0}/K$/{pp(1)}/M$/{pp(2)}/G$/{pp(3)}/T$/{pp(4)}/[^0-9KMGT]$/{print 0}' dehumanise
    937
    1464
    126143692
    5368709120
    1001801121792
    13414041858867
    0
    0
    

    【讨论】:

      猜你喜欢
      • 2013-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-15
      • 2021-10-31
      • 1970-01-01
      相关资源
      最近更新 更多