2012-05-26 8 views
8

Jest to adres IP: 66.102.13.19, i z tego adresu jako że otrzymał ten adresConverter

http://1113984275 

ale jak? I jak mogę to zrobić za pomocą basha. Na przykład, this service może to zrobić, ale nie rozumiem algorytmu.

Odpowiedz

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

Nawiasem mówiąc, liczba w pytaniu nie odpowiada adresowi IP.

Aby zamienić ułamek dziesiętny na 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]" 

przekonwertować IP do dziesiętnych:

#!/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]" 

Demo:

$ ./dec2ip 1113984275 
66.102.13.19 

$ ./ip2dec 66.102.13.19 
1113984275 

Te dwa skrypty polegać na cechach Bash, które nie są obecne w niektórych pociskach pochodzących z Bourne'a. Oto wersje AWK używać zamiast:

#!/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) 
} 

i

#!/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) 
} 

Można je wywołać w taki sam sposób, jak w bashu powyżej.

+0

Jaka jest liczba? –

+0

@AshBurlaczenko: Liczba dziesiętna dla danego adresu IP to 1113984275 –

+0

Dziękuję za decyzję, bardziej zrozumiałe, poprawiłem błąd. A jak działa odwrotność? Od 1113984275, aby uzyskać 66.102.13.19. – KarlsD

7

adres IP -> Numer: echo 66.102.13.19 | tr . '\n' | awk '{s = s*256 + $1} END{print s}' Number -> adres IP: (export ip=1113984275; for i in {1..4}; do s='.'$((ip%256))$s && ((ip>>=8)); done; echo ${s:1})

+0

To świetnie, ale jak robimy to w inny sposób. tj. numer IP -> adres IP – bsmoo

+1

Mam zaktualizowaną metodę konwersji numeru IP na adres IP. :) –

+0

Możesz uniknąć wywołania 'tr', określając separator rekordów, np .:' awk 'BEGIN {RS = "."} ... 'lub' awk' {s = s * 256 + $ 1} END {print s} 'RS = .' – bufh

3

moja wersja dla int IP konwersję:

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

3

Oto moje zdanie:

$ 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} 
+0

Uwielbiam to. ip2d może być funkcją (bash) jako 'ip2d() {IFS =. eval "set - $ 1"; echo ... 'i d2ip można również zapisać' IFS = \ read -rabcd <<(echo "obase = 256; $ 1" | bc) ' – bufh

+0

I znów krótszy:' A = ($ (dc -e "256o $ 1 p ")); IFS =. eval 'echo "$ {A [*] # 0}" "(mają ten sam numer niż oryginał, gdy quad ma dwa wiodące 0). – bufh

1

myślę, że to prostsze rozwiązanie, które obsługuje również dowolną liczbę oktetów bez odniesienia do stałych przesunięć itp

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

wyjściowa: 1113984275

+0

Witam, mam pytanie dotyczące Twojej odpowiedzi. Czy możesz wyjaśnić znaczenie '$ ((2 # $ (cat))' –

+1

@yundongxu Komenda 'cat' odczytuje dane przesyłane do standardowego wejścia, które jest łańcuchem cyfr binarnych. Wyrażenie "$ ((2 # ...))" konwertuje "..." z podstawy 2 na dziesiętne. –

2

Zmiana binarna jest zawsze szybsza niż pomnożenie lub dzielenie.
Używanie binarnego ORAZ jest szybsze niż mod.

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 " 

Uwaga: ten system zawiedzie z wartościami takimi jak 0008.
Bash myśli, że jest to liczba ósemkowa.

Aby rozwiązać że każda wartość będzie musiał być oczyszczony z czymś takim:

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

dla (bardzo) starych powłok: bash od 2,04 lub myślnikiem lub (rozsądnym) powłoka:

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 " 
Powiązane problemy