Emil Davtyan Emil Davtyan -4 years ago 145
Perl Question

Perl String to Base36

How do I convert a string to base36 (0-9,a-z) in perl?

I want to convert IP addresses to base36 with a one to one map, so I can use them in a URL.

127.0.0.1

=== string ==>
127000000001
=== base36 ==>

72.98.234.11

=== string ==>
072098234011
=== base36 ==>

Answer Source

Isn't base 10 good enough? That gives a number in [0-4294967295] (1 to 10 digits). That's only slightly longer than what you we were going to get from your way (1 to 8 digits).

$ perl -E'say unpack "N", pack "C4", split /\./, $ARGV[0]' 127.0.0.1
2130706433

$ perl -E'say unpack "N", pack "C4", split /\./, $ARGV[0]' 72.98.234.11
1214441995

Completely reversible:

$ perl -E'say join ".", unpack "C4", pack "N", $ARGV[0]' 2130706433
127.0.0.1

$ perl -E'say join ".", unpack "C4", pack "N", $ARGV[0]' 1214441995
72.98.234.11

You could convert that number to another base other than 10 using any number of modules on CPAN.

base 10: 1-10 digits
base 16: 1-8 digits    # Can be done very efficiently
base 32: 1-7 digits    # Can be done very efficiently
base 36: 1-7 digits
base 62: 1-6 digits
base 64: 1-6 digits    # Can be done very efficiently

Base 16:

sub pack_ip { sprintf "%X", unpack "N", pack "C4", split /\./, $_[0] }

sub unpack_ip { join ".", unpack "C4", pack "N", hex $_[0] }

Base 64: (This should be quite speedy. Faster even if ported to C.)

my @syms = ('0'..'9', 'A'..'Z', 'a'..'z', '_', '-');
my %syms = map { $sym[$_] => $_ } 0..$#syms;

sub pack_ip {
   my $num = unpack "N", pack "C4", split /\./, $_[0];
   my $base64 = join '', @syms[
      ($num >> 30) & 0x3F,
      ($num >> 24) & 0x3F,
      ($num >> 18) & 0x3F,
      ($num >> 12) & 0x3F,
      ($num >>  6) & 0x3F,
      ($num >>  0) & 0x3F,
   ];
   $base64 =~ s/^A+(?!\z)//;
   return $base64;
}

sub unpack_ip {
   my $num;
   $num = ($num << 6) | $sym{$_}
      for split //, $_[0];
   return join ".", unpack "C4", pack "N", $num;
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download