Преобразователь IP-адресов

Существует IP-адрес: 66.102.13.19, и с этого адреса, который получил этот адрес

http://1113984275

Но как? И как я могу сделать это с помощью bash. Например, эта служба может это сделать, но я не понимаю алгоритм.

Ответ 1

ip=66.102.13.19
IFS=. read -r a b c d <<< "$ip"
printf '%s%d\n' "http://" "$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))"

Кстати, номер вашего вопроса не соответствует IP-адресу.

Чтобы преобразовать десятичное число в IP:

#!/bin/bash
dec2ip () {
    local ip [email protected]
    for e in {3..0}
    do
        ((octet = dec / (256 ** e) ))
        ((dec -= octet * 256 ** e))
        ip+=$delim$octet
        delim=.
    done
    printf '%s\n' "$ip"
}

dec2ip "[email protected]"

Чтобы преобразовать IP в десятичный знак:

#!/bin/bash
ip2dec () {
    local a b c d [email protected]
    IFS=. read -r a b c d <<< "$ip"
    printf '%d\n' "$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))"
}

ip2dec "[email protected]"

Демо:

$ ./dec2ip 1113984275
66.102.13.19

$ ./ip2dec 66.102.13.19
1113984275

Эти два сценария полагаются на функции Bash, которые отсутствуют в некоторых оболочках, полученных из Bourne. Здесь используются версии AWK:

#!/usr/bin/awk -f
# dec2ip
BEGIN {
    dec = ARGV[1]
    for (e = 3; e >= 0; e--) {
        octet = int(dec / (256 ^ e))
        dec -= octet * 256 ^ e
        ip = ip delim octet
        delim = "."
    }
    printf("%s\n", ip)
}

и

#!/usr/bin/awk -f
# ip2dec
BEGIN {
    ip = ARGV[1]
    split(ip, octets, ".")
    for (i = 1; i <= 4; i++) {
        dec += octets[i] * 256 ** (4 - i)
    }
    printf("%i\n", dec)
}

Они могут быть вызваны так же, как и скрипты Bash выше.

Ответ 2

IP-адрес → Номер:

echo 66.102.13.19 | tr . '\n' | awk '{s = s*256 + $1} END{print s}'

Номер → IP-адрес:

(export ip=1113984275; for i in {1..4}; do s='.'$((ip%256))$s && ((ip>>=8)); done; echo ${s:1})

Ответ 3

моя версия для преобразования int в ip:

echo 3232235521| awk {'print rshift(and($1, 0xFF000000), 24) "." rshift(and($1, 0x00FF0000), 16) "." rshift(and($1, 0x0000FF00), 8) "." and($1, 0x000000FF) '}

Ответ 4

Вот мой прием:

$ host google.com
google.com has address 216.58.216.142
$ ./ip2d.sh 216.58.216.142
3627735182
$ ./d2ip.sh 3627735182
216.58.216.142

ip2d.sh:

#!/bin/bash

IFS=.
set -- $*
echo $(( ($1*256**3) + ($2*256**2) + ($3*256) + ($4) ))

d2ip.sh:

#!/bin/bash

IFS=" " read -r a b c d  <<< $(echo  "obase=256 ; $1" |bc)
echo ${a#0}.${b#0}.${c#0}.${d#0}

Ответ 5

Двоичное смещение всегда быстрее, чем умножение или деление. Использование двоичного файла AND быстрее, чем мода.

ip2dec(){ # Convert an IPv4 IP number to its decimal equivalent.
          declare -i a b c d;
          IFS=. read a b c d <<<"$1";
          echo "$(((a<<24)+(b<<16)+(c<<8)+d))";
        }
dec2ip(){ # Convert an IPv4 decimal IP value to an IPv4 IP.
          declare -i a=$((~(-1<<8))) b=$1; 
          set -- "$((b>>24&a))" "$((b>>16&a))" "$((b>>8&a))" "$((b&a))";
          local IFS=.;
          echo "$*";
        }

ip=66.102.13.19
a=$(ip2dec "$ip")
b=$(dec2ip "$a")
echo "$ip DecIP=$a IPv4=$b "

Примечание. Эта система выйдет из строя со значениями, такими как 0008.
Bash считает, что это восьмеричное число.

Чтобы решить это, каждое значение нужно будет очистить чем-то вроде:

IsDecInt()(     # Is the value given on $1 a decimal integer (with sign)?
                declare n=$1; set --
                if [[ $n =~ ^([+-]?)((0)|0*([0-9]*))$ ]]; then
                    set -- "${BASH_REMATCH[@]:1}"
                else
                    exit 1
                fi
                echo "$1$3$4";
          )

  a=$(IsDecInt "$a")||{ Echo "Value $a is not an integer" >&2; exit 1; }

Для (очень) старых оболочек: bash с 2.04, или тире или любой (разумной) оболочки:

ip2dec(){ # Convert an IPv4 IP number to its decimal equivalent.
          local a b c d;
          IFS=. read a b c d <<-_EOF_
$1
_EOF_
          echo "$(((a<<24)+(b<<16)+(c<<8)+d))";
        }

dec2ip(){   # Convert an IPv4 decimal IP value to an IPv4 IP.
            local a=$((~(-1<<8))) b=$1; 
            set -- "$((b>>24&a))" "$((b>>16&a))" "$((b>>8&a))" "$((b&a))";
            local IFS=.;
            echo "$*";
        }

ip=$1
a=$(ip2dec "$ip")
b=$(dec2ip "$a")
echo "$ip DecIP=$a IPv4=$b "

Ответ 6

Я думаю, что есть более простое решение, которое также обрабатывает произвольное количество октетов без ссылок на фиксированные смещения и т.д.

echo 66.102.13.19 |
    tr . '\n' |
    while read octet; do
        printf "%.08d" $(echo "obase=2;$octet" | bc)
    done |
    echo $((2#$(cat)))

: 1113984275

Ответ 7

Простое преобразование int в IP для bash

dec2ip ()
{
   local v=$1
   local i1=$((v>>24&255))
   local i2=$((v>>16&255))
   local i3=$((v>>8&255))
   local i4=$((v&255))
   printf '%d.%d.%d.%d\n' $i1 $i2 $i3 $i4
}