如何在bash中有效地将long int转换为点分四进制IP

时间:2010-07-11 08:28:50

标签: mysql bash

我在一个存储为long int的大型mysql数据库中有很多IP地址。我需要一种有效/快速的方法将它们转换回BASH shell脚本中的IP(或者让mysql将结果作为IP返回)。

注意:特别是不想调用perl,awk或其他“语言”。

6 个答案:

答案 0 :(得分:15)

因为你要求Bash:

INET_NTOA() { 
    local IFS=. num quad ip e
    num=$1
    for e in 3 2 1
    do
        (( quad = 256 ** e))
        (( ip[3-e] = num / quad ))
        (( num = num % quad ))
    done
    ip[3]=$num
    echo "${ip[*]}"
}

INET_ATON ()
{
    local IFS=. ip num e
    ip=($1)
    for e in 3 2 1
    do
        (( num += ip[3-e] * 256 ** e ))
    done
    (( num += ip[3] ))
    echo "$num"
}

示例:

$ INET_ATON 10.2.1.255
167903743
$ INET_NTOA 167903743
10.2.1.255

这个版本适用于我尝试过的任何Bourne派生的shell,包括dash,ksh,几个版本的Bash,BusyBox ash,zsh(带-y)甚至是Heirloom Bourne Shell

INET_NTOA() {
    num=$1
    ip=
    for e in 3 2 1
    do
        quad=`echo "256 ^ $e" | bc`
        if [ -n "$ip" ]
        then
            ip=$ip.
        fi
        ip=$ip`echo "$num / $quad" | bc`
        num=`echo "$num % $quad" | bc`
    done
    ip=$ip.$num
    echo "$ip"
}

INET_ATON ()
{
    num=0
    e=3
    saveIFS=$IFS
    IFS=.
    set -- $1
    IFS=$saveIFS
    for ip in "$@"
    do
        num=`echo "$num + $ip * 256 ^ $e" | bc`
        e=`echo "$e - 1" | bc`
    done
    echo "$num"
}

答案 1 :(得分:10)

请参阅INET_NTOA函数,您可以使用该函数将数字转换为MySQL服务器上的IP。

答案 2 :(得分:3)

INET_ATON()
  {
  local IFS=. ipStr

  ipStr=($1)
  echo $(($(($(($(($(($((${ipStr[0]} * 256)) + ${ipStr[1]})) * 256)) + ${ipStr[2]})) * 256)) + ${ipStr[3]}))
  }

INET_NTOA()
  {
  echo "$(($1 / 16777216)).$(($(($1 % 16777216)) / 65536)).$(($(($1 % 65536)) / 256)).$(($1 % 256))"
  }

subnetRange()
  {
  local addr=$(INET_ATON "$1") mask=$(INET_ATON "$2")

  echo "$(INET_NTOA $(($addr & $mask))) $(INET_NTOA $(($addr | $mask ^ 4294967295)))"
  }


答案 3 :(得分:1)

假设您在名为ip_addr

的表格中有一个名为hosts的字段

然后

select INET_NTOA(ip_addr) from hosts;

查询并返回结果集中的点分四进制IP。

答案 4 :(得分:1)

鉴于原始问题是关于在bash中执行此操作的高效方式,我认为这些可能是比赛中值得参赛的条目:

INET_ATON()
  {
  local IFS=. ip
  ip=($*)
  echo $(((ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3]))
  }

INET_NTOA()
  {
  echo $(($1 >> 24)).$((($1 >> 16) % 256)).$((($1 >> 8) % 256)).$(($1 % 256))
  }

当然,这些问题与此处给出的其他解决方案具有相同的“包装”问题,因为shell将整数视为已签名。

答案 5 :(得分:0)

我很懒,这已经完成了。所以从shell

$ ping -c1 1199092913 | head -n1 | grep -Eow "[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+"

我确信还有其他聪明的方法可以从shell中做到这一点。