Im having a file with ip address in this format
192.168.1.9
192.168.1.10
192.168.1.8
that i read to a list like this
with open("file.txt") as f:
ipaddr = f.read().splitlines()
And then run some functions on.
However, i would also be able to put in network address in this document as in
192.168.0.0/25 and somehow get them translated in the list as
192.168.0.1
192.168.0.2
192.168.0.3
I dont even have a clue how to accomplish this? (running Python 2.6)
The netaddr is one of the best ways to do this:
import netaddr
with open('file.txt') as f:
for line in f:
try:
ip_network = netaddr.IPNetwork(line.strip())
except netaddr.AddrFormatError:
# Not an IP address or subnet!
continue
else:
for ip_addr in ip_network:
print ip_addr
For the example file of:
10.0.0.1
192.168.0.230
192.168.1.0/29
The output it gives is:
10.0.0.1
192.168.0.230
192.168.1.0
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.5
192.168.1.6
192.168.1.7
You need to parse your text file with a regular expression. Look up for the 're' module in Python. A quick implementation of this idea is:
import re
with open("ips.txt") as f:
ip_raw_list = f.read().splitlines()
#Only takes the string after the '/'
reg_ex_1 = r'(?<=/)[0-9]*'
#Only take the first three numbers "0.0.0" of the IP address
reg_ex_2 = r'.*\..*\..*\.'
ip_final_list = list()
for ip_raw in ip_raw_list:
appendix = re.findall(reg_ex_1, ip_raw)
#Ip with no backslash create on input
if not appendix:
ip_final_list.append(ip_raw)
#Ip with backslash create several inputs
else:
for i in range(int(appendix[0])):
ip_final_list.append(re.findall(reg_ex_2, ip_raw)[0] + str(i))
This code uses the power of regular expression to separate IPs of the form '0.0.0.0' from IPs of the form '0.0.0.0/00'. Then for IPs of the first form, you put the IP directly on the final list. For IPs of the second for, you run a for loop to put several inputs in the final list.
Related
I am trying to retrieve few information regarding my perforce client using python script. I only want to fetch information related to server address, cleint root etc. as follows:
ping_string = subprocess.Popen(['p4', 'info','ls'], stdout=subprocess.PIPE ).communicate()[0]
print ping_string
So i get output as:
User name: hello
Client name: My_machine
Client host: XYZ
Current directory: c:\
Peer address: 1.2...
Client address: 1.102....
Server address: abcd
Server root: D:\scc\data
But as i want to retrieve server address, client address etc so, for that i want output to be in form of a list. So, please suggest how can i get the output as list type.
Using check_output simplifies getting the command output, so you could do:
out = subprocess.check_output(cmd)
lines = out.splitlines()
Note that each line will contain the trailing new line character.
Or if you want the data after the colons:
lines = [l.split(':', 1)[1].strip() for l in out.splitlines()
if ':' in l]
l.split(':', 1)[1] is taking the whatever is after the colon.
.strip() removes the surrounding whitespaces.
if ':' in l is a protection against lines that don't contain a colon.
I have a text file which include many ips in this format
Host : x.x.x.x , DNS : resolved dns , Location : USA
Host : x.x.x.x , DNS : resolved dns , Location : USA
Host : x.x.x.x , DNS : resolved dns , Location : USA
I want to take the VALID ips after the phrase "Host : " which is the first word in the line and move it to file ipclear.txt , discarding any ip from the same line just the Valid ip after the phrase Host .
f = open('inputfile.txt','r')
clearip = open('clearip.txt','w')
for line in f:
ip = line.split(',')[0].split(':')[1].strip()
clearip.write(ip+'\n')
f.close() # you can omit in most cases as the destructor will call if
clearip.close()
This will open two files, one is the file you're reading from, the other is the file you're writing to. Then it will go through the input file line by line. For each line we split it at the ,s, then the :s, assuming the file is in the same format that you posted, this will leave us with the IP address, which we then call strip() on to remove any trailing or leading whitespace. We then write this IP to the output file, and add the newline character. After this we close the text files.
Python's socket package has a function that converts a valid IP of dotted octets to an integer. It's called inet_aton, which is short for 'internet address to number'.
The try: [...] except: attempts to convert the string between 'Host :' and ' , DNS : ' to an IP integer, and it if fails, it just quietly moves on to the next line. It's easier to leverage socket than write your own regex to parse out all the possible valid IP's.
import re
import socket
ipPattern = re.compile('Host : (.*) , DNS : .*')
outfile = open('ipclear.txt', 'w')
for line in open('iplog.txt').readlines():
ipString = ipPattern.match(line).group(1)
try:
socket.inet_aton(ipString)
outfile.write(ipString + '\n')
except:
pass
outfile.close()
I have a script written to push config to network devices and/or print the output from various commands into files, backup etc.
This works perfectly well for individual devices when I define the IP of the device. I am not sure how I can write a loop in order for it to go through a file containing multiple IPs, and for it to run the commands on them one-by-one? Ie. i have a file IP.txt containing this:
1.1.1.1
2.2.2.2
3.3.3.3
This is my script:
import pexpect
HOST = "1.1.1.1"
user = "user"
password = "pass"
policymap = pexpect.spawn ('telnet '+HOST)
policymap.expect ('Username: ')
policymap.sendline (user)
policymap.expect ('Password: ')
policymap.sendline (password)
routerHostname = "router"
policymap.expect (router+'#')
policymap.sendline ('sh ip int br\r')
etc etc.
Just trying to figure out how can I have the script run through a list of IPs in a file and run the commands? Sorry for being amateurish here, I am new to this and working my way through a book to learn properly... but find this very helpful for questions :)
with open("IP.txt") as ips:
all_ips = [x.rstrip() for x in ips] # get all ips in a list and strip newline
for ip in all_ips:
policymap = pexpect.spawn ('telnet '+ ip) # first loop it will be 1.1.1.1, second loop it will be 2.2.2.2 etc..
all_ips will look like ['1.1.1.1', '2.2.2.2', '3.3.3.3']
The user will input either hostname or the IP address. If the user enters the IP address, I want to leave as it is but if the user enters the hostname I want to convert it into IP address using the following method:
def convert(hostname):
command = subprocess.Popen(['host', hostname],
stdout=subprocess.PIPE).communicate()[0]
progress1 = re.findall(r'\d+.', command)
progress1 = ''.join(progress1)
return progress1
How do I do it?
To get ip whether input is ip or hostname:
ip4 = socket.gethostbyname(ip4_or_hostname)
you can use a regex to match your input and test if it is a ip address or not
test = re.compile('\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b')
result = test.match(hostname)
if not result:
# no match -> must be an hostname #
convert(hostname)
that regex allows invalid ip addresses (like 999.999.999.999) so you may want to tweak it a bit, it's just a quick example
There are a number of questions on stackoverflow already about validating an IP address.
IP Address validation in python
Validating IP Addresses in python
I would like to ask why you are communicating with a subprocess when you can do this within the standard python library.
I would recommend resolving a host name into a IP address by using some of pythons built in functionality.
You can do this by importing and using the python sockets library
For example using the code found in link 1:
import socket
import re
regex = re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
result = regex.match(address)
if not result:
address = socket.gethostbyname(address)
In my case, host name can only contain - as a separator. So you can uncomment and use it according to your requirement.
import re
regex = "^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$"
# string_check= re.compile('[#_!#$%^&*()<>?/\|}{~:.]')
string_check= re.compile('[-]')
ip_host_detail = {}
def is_valid_hostname_ip(IpHost):
# pass regular expression and ip string into search() method
if (re.search(regex, IpHost)):
print("Valid Ip address")
ip_host_detail['is_ip'] = 'True'
ip_host_detail['is_hostname'] = 'False'
return True
elif(string_check.search(IpHost)):
print("Contain hostname")
ip_host_detail['is_hostname'] = 'True'
ip_host_detail['is_ip'] = 'False'
return True
else:
print("Invalid Ip address or hostname:- " + str(IpHost))
ip_host_detail['is_hostname'] = 'False'
ip_host_detail['is_ip'] = 'False'
return False
IpHost = sys.argv[1]
# IpHost = 'RACDC1-VM123'
is_valid_hostname_ip(IpHost)
print(ip_host_detail)
What's the most Pythonic way to create a list of the addressable IP addresses given a netaddr IPRange or netaddr IPNetwork.
If I use these, then it includes subnet and broadcast addresses:
hosts = list(IPRange('212.55.64.0','212.55.127.255'))
hosts = IPNetwork('192.168.0.1/24')
So what I need for say IPNetwork(192.168.0.0/27) is a list from 192.168.0.1 to 192.168.0.31 note that 192.168.0.0 and 192.168.0.32 must not be included.
EDIT
Thanks for info on how to do it with IPy. Does anybody know if it can be done with netaddr?
The following is a quick script to do what you want using netaddr
(Python 2.7, linux)
from netaddr import *
def addr(address, prefix):
ip = IPNetwork(address)
ip.prefixlen = int(prefix)
return ip
myip = addr('192.168.0.0', '27')
for usable in myip.iter_hosts():
print '%s' % usable
After doing a bit of research I found this way:
l = list(netaddr.IPNetwork('192.168.0.0/27').iter_hosts())