【问题标题】:Batch Convert IP Addresses into Decimals?将 IP 地址批量转换为十进制?
【发布时间】:2017-04-23 08:34:16
【问题描述】:

我有一个大文件,每行包含 2 个IPs - 总共大约有 300 万行。

这是文件的一个示例:

1.32.0.0,1.32.255.255
5.72.0.0,5.75.255.255
5.180.0.0,5.183.255.255
222.127.228.22,222.127.228.23
222.127.228.24,222.127.228.24

我需要将每个IP 转换为IP Decimal,如下所示:

18874368,18939903
88604672,88866815
95682560,95944703
3732923414,3732923415
3732923416,3732923416

我更喜欢通过命令行严格执行此操作的方法。我可以使用 perlpython,只要它不需要安装额外的模块。

我以为我遇到了一种方法,有人像这样使用 sed 转换了 IPs,但似乎再也找不到那个教程了。任何帮助将不胜感激。

【问题讨论】:

标签: bash shell sed command-line ip-address


【解决方案1】:

这是python 解决方案,仅使用标准模块(re、sys):

import re
import sys

def multiplier_generator():
    """  Cyclic generator of powers of 256 (from 256**3 down to 256**0)
        The mulitpliers tupple could be replaced by inline calculation
    of power, but this approach has better performance.
    """ 
    multipliers = (
        256**3,
        256**2,
        256**1,
        256**0,
    )
    idx = 0
    while 1 == 1:
        yield multipliers[idx]
        idx = (idx + 1) % 4

def replacer(match_object):
    """re.sub replacer for ip group"""
    multiplier = multiplier_generator()
    res = 0
    for i in xrange(1,5):
        res += multiplier.next()*int(match_object.group(i))
    return str(res)

if __name__ == "__main__":
    std_in = ""
    if len(sys.argv) > 1:
        with open(sys.argv[1],'r') as f:
            std_in = f.read()
    else:
        std_in = sys.stdin.read()
    print re.sub(r"([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)", replacer, std_in )

此解决方案替换每个 IP 地址,可以在标准输入的文本或作为第一个参数传递的文件中找到,即:

  • python convert.py
  • python convert.py file.txt,或者
  • 回显“1.2.3.4, 5.6.7.8” | python convert.py。

【讨论】:

  • 感谢您的回答!我会在您的脚本中的哪个位置指定我需要在 test.txt 上运行它?
  • 它完全符合我的要求,但数学上似乎有些不对劲。如果您尝试通过脚本运行我上面的示例 IP,它会给出不同的 IP 十进制数:/
【解决方案2】:

如果你安装了 gnu awk(对于 RT 变量),你可以使用这个单行:

awk -F. -v RS='[\n,]' '{printf "%d%s", (($1*256+$2)*256+$3)*256+$4, RT}' file
18874368,18939903
88604672,88866815
95682560,95944703
3732923414,3732923415
3732923416,3732923416

【讨论】:

  • 没问题,性能更好,但显示IP是科学格式。
  • @MarekNowaczyk:这很奇怪,在我的系统上,输出就像上面一样(我从终端复制粘贴)。我的 awk 是 GNU awk 4.1.3。你用的是什么版本?尝试使用"%d%s" 作为格式字符串...
【解决方案3】:

使用 bash:

ip2dec() {
  set -- ${1//./ }     # split $1 with "." to $1 $2 $3 $4
  declare -i dec       # set integer attribute
  dec=$1*256*256*256+$2*256*256+$3*256+$4
  echo -n $dec
}

while IFS=, read -r a b; do ip2dec $a; echo -n ,; ip2dec $b; echo; done < file

输出:

18874368,18939903 88604672,88866815 95682560,95944703 3732923414,3732923415 3732923416,3732923416

【讨论】:

    【解决方案4】:

    使用 bash 并使用移位(一条 CPU 指令)而不是乘法(大量指令):

    ip2dec() {  local IFS=.
                set -- $1     # split $1 with "." to $1 $2 $3 $4
                printf '%s' "$(($1<<24+$2<<16+$3<<8+$4))"
             }
    
    while IFS=, read -r a b; do
        printf '%s,%s\n' "$(ip2dec $a)" "$(ip2dec $b)"
    done < file
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-13
      • 1970-01-01
      • 2016-07-05
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 2020-08-08
      • 2012-08-21
      相关资源
      最近更新 更多