Reputation: 559
I have the following code, what I am trying to do is create a small function so a when an IP range (contains : in it) is inputted all range is appended to the list.
collected_ips = []
while True:
query = input("IP:\t")
if not query:
break
elif len(query.split('.'))==4:
temp = query.split('.')
#result1 = all([i.isdigit() for i in t]) #must be True
if query.find(":")==-1:
try:
result2 = all([0<=int(i)<=255 for i in temp])
if result2:
collected_ips.append(query)
except ValueError:
print("Please Fix Input")
elif len(x.split(":"))==2:
#function here
#append to collected_ips
else:
print("Please Fix Input")
else:
print("Please Fix Input")
example of input:
123.123.30.20:50
output:
['123.123.30.20,'123.123.30.21'...'123.123.30.50']
example of input:
123.123.20:50.30
output:
['123.123.20.30','123.123.21.30',...'123.123.50.30']
Upvotes: 2
Views: 150
Reputation: 42129
You could also do this more concisely using reduce (from functools):
from functools import reduce
def expandIp(ip):
nodes = [list(map(int,n.split(":"))) for n in ip.split(".")]
ranges = [range(max(n[0],0),min(n[-1]+1,256)) for n in nodes]
ips = reduce(lambda a,rng: [ip+[n] for ip in a for n in rng],ranges,[[]])
return [".".join(str(n) for n in ip) for ip in ips]
nodes
converts the ip pattern into a list of range values [start] or [start,end]ranges
converts the nodes into actual ranges using the start number as the end when there is not a ':' specifier for the node (also caps the node to range 0...255)ips
combines each node range with all values of preceding nodesnote: this solution will work for multiple range specifiers in the ip parameter. e.g. expandIp("10.1.1:2.100:101")
will produce: 10.1.1.100, 10.1.1.101, 10.1.2.100, 10.1.2.101. So if you intend to use it for subnets, you will be able to do expandIp("10.0.1:3.0:255")
By the way, you could validate the ip
parameter with a single condition at the beginning of the function or before calling it (then you wouldn't need to use min/max to assign the ranges
variable):
n0255 = { str(n) for n in range(256) }
if not all( i<4 and j<2 and r in n0255 for i,n in enumerate(ip.split(".")) for j,r in enumerate(n.split(":"))):
print("Invalid Input")
The final function would look like this:
from functools import reduce
n0255 = { str(n) for n in range(256) }
def expandIp(ip):
if not all( i<4 and j<2 and r in n0255 for i,n in enumerate(ip.split(".")) for j,r in enumerate(n.split(":"))):
return None
nodes = [list(map(int,n.split(":"))) for n in ip.split(".")]
ranges = [range(n[0],n[-1]+1) for n in nodes]
ips = reduce(lambda a,rng: [ip+[n] for ip in a for n in rng],ranges,[[]])
return [".".join(str(n) for n in ip) for ip in ips]
which would simplify your calling code down to :
collected_ips = []
while True:
query = input("IP:\t")
if not query:
break
ips = expandIp(query)
if not ips:
print("Invalid Input")
else:
collected_ips += ips
Upvotes: 1
Reputation: 26057
This is one approach using range
to generate numbers between two ranges:
def spread_ip_range(ip):
splits = ip.split('.')
indx = next((i for i, x in enumerate(splits) if ':' in x), -1)
lst = []
if indx != -1:
_from, to = splits[indx].split(':')
ranges = range(max(0, int(_from)), min(255, int(to)) + 1))
for r in ranges:
s = '.'.join(splits[:indx]) + '.' + str(r)
if splits[indx+1:]:
s += '.' + '.'.join(splits[indx+1:])
lst.append(s)
return lst
Usage:
>>> spread_ip_range('123.123.20:50.30')
['123.123.20.30', '123.123.21.30', '123.123.22.30', ......, '123.123.49.30', '123.123.50.30']
-
>>> spread_ip_range('123.123.30.20:50')
['123.123.30.20', '123.123.30.21', '123.123.30.22', ......, '123.123.30.49', '123.123.30.50']
Upvotes: 1