2010-04-01 50 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

相關問題