bash IP地址转换器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10768160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 22:09:22  来源:igfitidea点击:

IP Address Converter

bashipconverter

提问by KarlsD

There is IP address: 66.102.13.19, and from this address as that received this address

有IP地址:66.102.13.19,从这个地址收到这个地址

http://1113984275

But how? And how I can make this with the help of bash. For example, this servicecan do it, but I do not understand the algorithm.

但是如何?以及我如何在 bash 的帮助下做到这一点。比如这个服务可以做到,但是我不懂算法。

回答by Paused until further notice.

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

By the way, the number in your question doesn't match the IP address.

顺便说一下,您问题中的数字与 IP 地址不匹配。

To convert a decimal to an IP:

要将十进制数转换为 IP:

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

dec2ip "$@"

To convert an IP to a decimal:

要将 IP 转换为十进制:

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

ip2dec "$@"

Demo:

演示:

$ ./dec2ip 1113984275
66.102.13.19

$ ./ip2dec 66.102.13.19
1113984275

These two scripts rely on features of Bash that aren't present in some Bourne-derived shells. Here are AWK versions to use instead:

这两个脚本依赖于一些 Bourne 派生的 shell 中不存在的 Bash 功能。以下是要使用的 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)
}

and

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

They can be called in the same manner as the Bash scripts above.

它们可以以与上述 Bash 脚本相同的方式调用。

回答by Hongbo Liu

IP address -> Number:

IP 地址 -> 号码:

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

Number -> IP address:

号码 -> IP 地址:

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

回答by Isaac

Binary shifting is always faster than multiplying or dividing.
Using a binary AND is faster than mod.

二进制移位总是比乘法或除法快。
使用二进制 AND 比 mod 快。

ip2dec(){ # Convert an IPv4 IP number to its decimal equivalent.
          declare -i a b c d;
          IFS=. read a b c d <<<"";
          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=; 
          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 "

Note: This system will fail with values like 0008.
Bash thinks it is an octal number.

注意:此系统将失败,并显示类似0008.
Bash 认为它是一个八进制数。

To solve that, each value will have to be cleaned with something like:

为了解决这个问题,每个值都必须用类似的东西来清理:

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

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

For (very) old shells: bash since 2.04, or dash or any (reasonable) shell:

对于(非常)旧的 shell:bash 自 2.04 或 dash 或任何(合理的)shell:

ip2dec(){ # Convert an IPv4 IP number to its decimal equivalent.
          local a b c d;
          IFS=. read a b c d <<-_EOF_

_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=; 
            set -- "$((b>>24&a))" "$((b>>16&a))" "$((b>>8&a))" "$((b&a))";
            local IFS=.;
            echo "$*";
        }

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

回答by vik

my version for int to ip conversion:

我的 int 到 ip 转换版本:

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

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

回答by evuraan

Here's my take:

这是我的看法:

$ 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:

ip2d.sh:

#!/bin/bash

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

d2ip.sh:

d2ip.sh:

#!/bin/bash

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

回答by Brian Chrisman

I think there's a simpler solution that also handles an arbitrary number of octets with no references to fixed offsets etc.

我认为有一个更简单的解决方案,它也可以处理任意数量的八位字节,而没有对固定偏移量的引用等。

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

output: 1113984275

输出:1113984275

回答by ken

Simple int to IP conversion for bash

bash 的简单 int 到 IP 转换

dec2ip ()
{
   local v=
   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
}