如何在 Perl 中将字符串转换为 Base36 (0-9,az)?
我想使用一对一映射将 IP 地址转换为 base36,这样我就可以在 URL 中使用它们。
127.0.0.1
=== 字符串 ==> 127000000001=== base36 ==>
72.98.234.11
=== 字符串 ==> 072098234011=== base36 ==>
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
Run Code Online (Sandbox Code Playgroud)
完全可逆:
$ 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
Run Code Online (Sandbox Code Playgroud)
您可以使用 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
Run Code Online (Sandbox Code Playgroud)
基地 16:
sub pack_ip { sprintf "%X", unpack "N", pack "C4", split /\./, $_[0] }
sub unpack_ip { join ".", unpack "C4", pack "N", hex $_[0] }
Run Code Online (Sandbox Code Playgroud)
Base 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;
}
Run Code Online (Sandbox Code Playgroud)