Конвертировать объем памяти (человек читаемый) в фактическое число (байты) в Perl - PullRequest
3 голосов
/ 01 апреля 2010

Есть ли в CPAN фактический пакет для преобразования такой строки:

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

в действительное число в байтах:

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

И наоборот.

В принципе, в конце я хочу суммировать весь объем памяти.

Ответы [ 4 ]

5 голосов
/ 01 апреля 2010

Чтобы получить точный вывод, который вы запрашивали, используйте Number :: FormatEng и Number :: 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 байтов. Возможно, поэтому он дает странный результат (с дробными байтами), если только он не округлен.

4 голосов
/ 01 апреля 2010

Для вашей первой проблемы я не нашел пакет 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 :: Format * format_number, если вам нужны красивые точки с запятой (например, «5,124» вместо «5124»)

CPAN решает вторую часть вашей проблемы:

Количество :: Б :: Human

Например:

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

Вы можете указать необязательный параметр bs => 1000 для изменения базы преобразования на 1000 вместо 1024.

1 голос
/ 01 апреля 2010

Это должно помочь вам начать. Вы можете добавить другие факторы, такие как килобайты («К»), а также форматирование вывода (например, разделители запятых):

#!/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
1 голос
/ 01 апреля 2010

В основном, чтобы перейти от строк к числам, все, что вам нужно, это единицы отображения хеша в множители:

#!/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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...