开发者

How to efficiently convert long int to dotted quad IP in bash [duplicate]

This question already has an answer here: 开发者_JAVA百科 Converting an IP to a Long in MySQL (1 answer) Closed 5 years ago.

I have a lot of IP addresses in a large mysql DB stored as long int's. I need an efficient/quick way to convert them back to an IP within a BASH shell script ( or have mysql return the results as an IP?? ).

Note: specifically don't want to call perl, awk, or other 'language'.


Since you asked for 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"
}

Examples:

$ INET_ATON 10.2.1.255
167903743
$ INET_NTOA 167903743
10.2.1.255

Here is a version that will work in any of the Bourne-derived shells I tried including dash, ksh, several versions of Bash, BusyBox ash, zsh (with -y) and even the 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"
}


See the INET_NTOA function, you can use that to convert the number to an IP on the MySQL server.


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)))"
  }



Suppose you have a field called ip_addr in a table called hosts

Then

select INET_NTOA(ip_addr) from hosts;

Would do the query and return dotted quad IPs in the result set.


Given that the original question was about an efficient way to do this in bash, I think these might be worthy entries in the contest:

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))
  }

Naturally, these have the same "wrapping" problem as the other solutions given here, due to the shell's treatment of integers as signed.


i'm lazy, and this has already been done. So from a shell

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

i'm sure there are other clever ways to do it from shell as well.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜