2012-09-26 67 views
0

如何在perl中將字符串轉換爲base36(0-9,a-z)?Perl字符串到Base36

我想用一對一的地圖將IP地址轉換爲base36,所以我可以在URL中使用它們。

127.0.0.1 ===串==>127000000001 === base36 ==>

72.98.234.11 ===串==>072098234011 === base36 ==>

+0

我發現'Math :: Base36'但編碼它想要一個int作爲參數,所以我試圖找到一種方法來將字符串轉換爲唯一的int。 –

+0

你可以使用int($ str)或者將字符串乘以1得到一個int – scrappedcola

回答

4

不是基10夠好嗎?這在[0-4294967295](1到10位數字)中給出了一個數字。這隻比你我們從你的方式得到的要長(1到8位)。

$ 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 

完全可逆的:

$ 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 

你可以這個數字轉換爲使用任意數量的CPAN模塊的超過10之外的其他基地。

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 

基地16:

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

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

基地64:(這應該是相當快捷的速度更快,即使移植到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; 
} 
+0

這看起來像我所需要的,實際上更好,因爲中間int這種方式更小,但是我會將該int插入到'Math :: Base36'它應該產生一個大約6個字符的字符串。 2130706433 => Z8KFLT –

+0

我想弄清楚這是否給出了一對一的地圖。分裂是無視期限,並可能導致衝突。 –

+0

增加了更多。是的,一對一的地圖。 – ikegami

-1

你爲什麼不使用基16因爲這基本上是一個IP地址是什麼?

sub ip_to_hex { 
    join('', map { sprintf('%02x', $_) } split(/\./, shift)); 
} 

sub hex_to_ip { 
    join('.', map { hex($_) } shift =~ m/([0-9a-f]{2})/g); 
} 

say ip_to_hex('127.0.0.1'); # 7f000001 
say ip_to_hex('72.98.234.11'); # 4862ea0b 
say hex_to_ip('4862ea0b');  # 72.98.234.11