Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Generate IP ranges from list of IP addresses

Tags:

python

arrays

I have a .csv file with list of IP addresses for few data centers. The list currently looks similar to the table below:

  Data_Center_Name      IP
              DC_1      52.102.182.2
              DC_1      52.102.182.4
              DC_1      52.102.182.1
              DC_1      52.102.182.5
              DC_1      52.102.182.3
              DC_1      27.101.178.17
              DC_1      27.101.178.16
              DC_1      27.101.178.15
              DC_1      23.201.165.7
              DC_2      55.200.162.10
              DC_2      55.200.162.12
              DC_2      55.200.162.13
              DC_2      55.200.162.11
              DC_3      30.101.102.4

I want to convert the lists into individual lists such as:

     DC_1 = [52.102.182.1-52.102.182.5,
             27.101.178.15-27.101.178.17,
             23.201.165.7]
     DC_2 = [55.200.162.10-55.200.162.13]
     DC_3 = [30.101.102.4]

Can anyone help me using python?

like image 337
Preetesh Gaitonde Avatar asked Oct 31 '17 18:10

Preetesh Gaitonde


1 Answers

My solution is:

  1. Convert each IP to decimal number

  2. Sort and get ranges (interval) from the list numbers

  3. Convert them to IP format.

Input:

ips = [ "52.102.182.2", "52.102.182.4", "52.102.182.1", "52.102.182.5", "52.102.182.3", 
        "27.101.178.17", "27.101.178.16", "27.101.178.15",
        "23.201.165.7", ]

Step 1:

IP => Binary => Decimal

# Convert ips to binary strings
bins = [''.join([bin(int(i))[2:].zfill(8) for i in ip.split('.')]) for ip in ips]

# Convert binary strings to decimal numbers
numbers = [int(b, 2) for b in bins]

or IP => Decimal

# Convert ips to decimal numbers
numbers = [sum((256 ** (3 - k)) * int(n) for k, n in enumerate(ip.split('.'))) for ip in ips]

Step 2:

# Sort decimal numbers
numbers.sort()

# Get ranges from decimal numbers
ranges = []
tmp = []
for i in range(len(numbers)):
    tmp.append(numbers[i])
    if (i == len(numbers) - 1) or (numbers[i + 1] > numbers[i] + 1):
        if len(tmp) == 1:
            ranges.append(tmp[0])
        else:
            ranges.append((tmp[0], tmp[-1]))
        tmp = []

Step 3:

# Convert dec ranges to ip ranges
def dec_to_ip(n):
    return '.'.join([str(int(n % 256 ** (4 - k) / 256 ** (3 - k))) for k in range(4)])

# Final result
ip_ranges = [(dec_to_ip(r[0]), dec_to_ip(r[1])) if type(r) == tuple else dec_to_ip(r) for r in ranges]

Output:

['23.201.165.7', ('27.101.178.15', '27.101.178.17'), ('52.102.182.1', '52.102.182.5')]
like image 129
Huu-Danh Pham Avatar answered Oct 07 '22 17:10

Huu-Danh Pham