Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert Memory Size (Human readable) into Actual Number (bytes) in Perl

Tags:

linux

unix

perl

Is there an actual package in CPAN to convert such string:

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

into the actual number in bytes:

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

And vice versa.

In principle what I want to do at the end is to sum out all the memory size.

like image 737
neversaint Avatar asked Dec 22 '22 04:12

neversaint


2 Answers

To get the exact output you asked for, use Number::FormatEng and 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             

By the way, only unformat_pref is needed if you are going to perform calculations with the result.

Since Number::FormatEng was intended for engineering notation conversion (not for bytes), its prefix is case-sensitive. If you want to use it for kilobytes, you must use lower case k.

Number::Format will convert these strings into actual bytes (kinda, almost).

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

The reason I said "kinda, almost" is that Number::Format treats 1K as being equal to 1024 bytes, not 1000 bytes. That's probably why it gives a weird-looking result (with fractional bytes), unless it is rounded.

like image 171
toolic Avatar answered Dec 27 '22 08:12

toolic


For your first problem, I did not find a CPAN package, but this code snippet might do:

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
}

Wrap the number through Number::Format's format_number function if you'd like pretty semi-colons (e.g. "5,124" instead of "5124")

CPAN solves the second part of your problem:

Number::Bytes::Human

For example:

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

You may provide an optional bs => 1000 parameter to change the base of the conversion to 1000 instead of 1024.

like image 37
rjh Avatar answered Dec 27 '22 07:12

rjh