2010-04-01 63 views
3

实际数(字节数)是否有实际的包在CPAN这种字符串转换:转换存储器大小(人类可读的)成在Perl

my $string = "54.4M" 
my $string2 = "3.2G" 

到实际数目字节:

54,400,000 
3,200,000,000 

反之亦然。

原则上我最终想做的是总结所有的内存大小。

+1

如果你已经在PerlMonks CB一分钟再到处挂着你会得到你的答案,基本上toolic的。 – MkV 2010-04-01 14:19:55

回答

5

要获得确切输出你要的,使用Number::FormatEngNumber::Format

use strict; 
use warnings; 

use Number::FormatEng qw(:all); 
use Number::Format qw(:subs); 

my $string = "54.4M" ; 
my $string2 = "3.2G" ; 

print format_number(unformat_pref($string)) , "\n"; 
print format_number(unformat_pref($string2)) , "\n"; 

__END__ 
54,400,000 
3,200,000,000    

顺便说一句,只有unformat_pref需要,如果哟你会用结果进行计算。

由于Number::FormatEng用于工程记法转换(不适用于字节),因此其前缀区分大小写。如果您想将其用于千字节,则必须使用小写字母k

Number::Format会将这些字符串转换为实际字节(有点差不多)。

use Number::Format qw(:subs); 

my $string = "54.4M" ; 
my $string2 = "3.2G" ; 

print round(unformat_number($string) , 0), "\n"; 
print round(unformat_number($string2), 0), "\n"; 

__END__ 
57042534 
3435973837 

我之所以说“有点,几乎”是Number::Format对待1K为等于1024个字节,而不是1000字节。这可能就是为什么它给出了一个奇怪的结果(小数字节),除非它是四舍五入的。

+0

什么是一个字节的0.4? – 2010-04-01 01:56:59

+0

@Alex Reynolds:我用圆圈数字更新了答案。 – toolic 2010-04-01 02:39:44

+1

这里有一个模块。对不起,我怀疑你,CPAN。 – rjh 2010-04-01 02:55:23

4

对于你的第一个问题,我没有找到一个CPAN包,但是此代码段可能会做:

sub convert_human_size { 
    my $size = shift; 
    my @suffixes = ('', qw(k m g)); 
    for my $index (0..$#suffixes) { 
     my $suffix = $suffixes[$index]; 
     if ($size =~ /^([\d.]+)$suffix\z/i) { 
      return int($1 * (1024 ** $index)); 
     } 
    } 
    # No match 
    die "Didn't understand human-readable file size '$size'"; # or croak 
} 

绕通Number::Formatformat_number功能的数量,如果你想漂亮分号(例如, “5,124”,而不是 “5124”)

CPAN解决您的问题的第二部分:

Number::Bytes::Human

例如:

use Number::Bytes::Human qw(format_bytes); 
    $size = format_bytes(54_400_000); 

你可以提供一个可选的bs => 1000参数转换的基础基本上更改为1000,而不是1024

+0

听起来像你应该打包第一个案例数::字节::不人道:-) – justintime 2010-04-01 02:29:00

1

,从字符串到数字去,你需要的是一个散列映射单元给乘法器:

#!/usr/bin/perl 

use strict; use warnings; 
my $base = 1000; 

my %units = (
    K => $base, 
    M => $base ** 2, 
    G => $base ** 3, 
    # etc 
); 

my @strings = qw(54.4M 3.2G 1K 0.1M .); 
my $pattern = join('|', sort keys %units); 

my $total; 

for my $string (@strings) { 
    while ($string =~ /(([0-9]*(?:\.[0-9]+)?)($pattern))/g) { 
     my $number = $2 * $units{$3}; 
     $total += $number; 
     printf "%12s = %12.0f\n", $1, $number;; 
    } 
} 

printf "Total %.0f bytes\n", $total; 

输出:

  54.4M =  54400000 
     3.2G = 3200000000 
      1K =   1000 
     0.1M =  100000 
Total 3254501000 bytes
+0

你确定你会使用10的权力? – 2010-04-01 01:55:36

+1

@Alex我不会。 IMNSHO,只有一个千字节的真正衡量标准,即1024字节。我不需要'KiB'废话;-)然而,OP使用10的幂,所以我就这样离开了它。 – 2010-04-01 01:58:37

+1

一个小小的改进就是增加一个$ base变量,这样你可以设置一次,仍然可以使单位全部解决。 :) – 2010-04-01 02:16:45

1

这应该让你开始。你可以在你自己添加其他因素,如千字节(“K”),以及输出格式(逗号分隔符,例如):

#!/usr/bin/perl -w 

use strict; 
use POSIX qw(floor); 

my $string = "54.4M"; 

if ($string =~ m/(\d+)?.(\d+)([M|G])/) { 
    my $mantissa = "$1.$2"; 
    if ($3 eq "M") { 
     $mantissa *= (2 ** 20); 
    } 
    elsif ($3 eq "G") { 
     $mantissa *= (2 ** 30); 
    } 
    print "$string = ".floor($mantissa)." bytes\n"; 
} 

输出:

54.4M = 57042534 bytes 
+0

这是我在“消除不必要的循环和分支”(http://www.effectiveperlprogramming.com/blog/23)中讨论的问题的反面,但您可以做出相同的改进。 :) – 2010-04-01 02:15:30

相关问题