shell 脚本中的单位乘数转换

jak*_*sky 3 shell bash arithmetic

我需要将人类可读的大小转换为字节。不幸的是,我无法访问 numfmt 函数。还有其他选择吗?我需要一个 shell/bash 函数来从 sh 脚本内部调用。

1K 应转换为 1000,1M 应转换为 1000 000 等。

Jos*_* R. 6

如果 Perl 可用:

echo your_string | perl -ne '
    BEGIN{ %suffixes=( K => 3, M => 6, G => 9, T => 12, P => 15, E => 18 ); 
           $suffix_regex = join "|", keys %suffixes;
    }
    s/([0-9][0-9]*(?:\.[0-9]+)?)($suffix_regex)/$1e$suffixes{$2}/g;
    printf "%d\n", $_;
'
Run Code Online (Sandbox Code Playgroud)

由于这将用作文本过滤器,因此将其定义为perl脚本并将输入管道输入其中更为合适。您可以通过将以下内容添加到您的.bashrc(假设您使用 Bash)将其嵌入到 shell 函数中:

myconvert() {
    cat <<'EOF' >/dev/null
#!--perl-- -n
BEGIN{ %suffixes=( K => 3, M => 6, G => 9, T => 12, P => 15, E => 18 ); 
       $suffix_regex = join "|", keys %suffixes;
}
s/([0-9][0-9]*(?:\.[0-9]+)?)($suffix_regex)/$1e$suffixes{$2}/g;
printf "%d\n", $_;
__END__
EOF
   exec perl -x "/path/to/your/.bashrc"
}
Run Code Online (Sandbox Code Playgroud)

使用sed和的解决方案bc

myconvert(){
  sed '
      s/\([0-9][0-9]*\(\.[0-9]\+\)\?\)K/\1*1000/g;
      s/\([0-9][0-9]*\(\.[0-9]\+\)\?\)M/\1*1000000/g;
      s/\([0-9][0-9]*\(\.[0-9]\+\)\?\)G/\1*1000000000/g;
      s/\([0-9][0-9]*\(\.[0-9]\+\)\?\)T/\1*1000000000000/g;
      s/\([0-9][0-9]*\(\.[0-9]\+\)\?\)P/\1*1000000000000000/g;
      s/\([0-9][0-9]*\(\.[0-9]\+\)\?\)E/\1*1000000000000000000/g
  ' </dev/stdin | bc | sed 's/\..*$//' # Final sed to remove decimal point
}
Run Code Online (Sandbox Code Playgroud)

用法(两种解决方案相同):

$ echo '5.23K' | myconvert
5230
$ echo '6.27G' | myconvert
6270000000
Run Code Online (Sandbox Code Playgroud)

此解决方案假定您的输入仅包含形式的字符串5.23K(小数部分可选),否则bc将不知道如何处理它们。

笔记

Perl one-liner 可以按原样插入到 shell 函数中,< /dev/stdin就像sed解决方案一样。在编写答案的第一个版本时,我并没有想到这一点。不过,我将把perl -x诀窍留在那里,以防它可以使其他人受益。