代码之家  ›  专栏  ›  技术社区  ›  antosr7

如何在PostgreSQL中将以:分隔的十六进制ipv6字符串转换为十进制

  •  0
  • antosr7  · 技术社区  · 7 年前

    我正在尝试将十六进制字符串转换为IPV6地址的数字列 十六进制输入为 2001:200:101:ffff:ffff:ffff:ffff:ffff 我的输出应该是 42540528727106952925351778646877011967 我尝试了以下从该站点获取的功能,通过使用 : 2001200101ffffffffffffffffffff

    `CREATE OR REPLACE FUNCTION hex_to_int(hexval varchar) RETURNS numeric AS $$
    DECLARE
      result  NUMERIC;
      i integer;
      len integer;
      hexchar varchar;
    BEGIN
    
      result := 0;
      len := length(hexval);
    
      for i in 1..len loop
        hexchar := substr(hexval, len - i + 1, 1);
        result := result + 16 ^ (i - 1) * case
          when hexchar between '0' and '9' then cast (hexchar as int)
          when upper (hexchar) between 'A' and 'F' then ascii(upper(hexchar)) - 55
        end;
      end loop;
    
     RETURN result;
    END;
    $$
    LANGUAGE 'plpgsql' IMMUTABLE STRICT;`
    

    我得到的十进制数为

    select hex_to_int('2001200101ffffffffffffffffffff');
                  hex_to_int
    --------------------------------------
     166176317495821453702777150266933247
    

    如何获得我的实际十进制数?

    1 回复  |  直到 7 年前
        1
  •  0
  •   Ron Maupin    7 年前

    问题中的十进制结果是问题中十六进制数字的正确结果。

    您缺少的是第二个和第三个IPv6地址字中被抑制的前导零。您未正确转换IPv6地址字符串表示形式( 2001:200:101:ffff:ffff:ffff:ffff:ffff )到实际十六进制数( 200102000101ffffffffffffffffffff )。请注意添加的零位数。每个IPv6单词是四个十六进制数字,但允许(RFC 5952要求)在字符串表示的单词中抑制前导零,但这并不意味着它们不存在。

    您需要确保每个IPv6地址字都是四个十六进制数字(添加任何缺失的零以达到四位数,并用正确的数字替换任何双冒号 0000 删除冒号之前。


    似乎没有任何真正、合法的理由将IPv6地址转换为十进制表示形式。IP地址(IPv4和IPv6)都是二进制数,IPv6的十六进制表示形式直接转换为二进制。在混合中加入十进制只是自找麻烦。